Last active
February 7, 2023 22:15
-
-
Save Semior001/c30baa51386b748a84bb33f4139e602a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package _example | |
import ( | |
"context" | |
_ "embed" | |
"fmt" | |
"regexp" | |
"strings" | |
"testing" | |
"time" | |
"github.com/cappuccinotm/grid" | |
"github.com/cappuccinotm/grid/gctrl" | |
"github.com/stretchr/testify/require" | |
) | |
//go:embed schedule.csv | |
var scheduleFile []byte | |
type timeSpan struct { | |
Start time.Time | |
End time.Time | |
} | |
func (t *timeSpan) UnmarshalGrid(ctx context.Context, anchor grid.Anchor) error { | |
v, err := anchor.Get(ctx, grid.RelativePos{}) | |
if err != nil { | |
return fmt.Errorf("get value: %w", err) | |
} | |
tokens := strings.Split(strings.TrimSpace(v), "-") | |
if len(tokens) != 2 { | |
return fmt.Errorf("invalid period: %s", v) | |
} | |
if t.Start, err = time.Parse("15:04", tokens[0]); err != nil { | |
return fmt.Errorf("parse start time: %w", err) | |
} | |
if t.End, err = time.Parse("15:04", tokens[1]); err != nil { | |
return fmt.Errorf("parse end time: %w", err) | |
} | |
return nil | |
} | |
func TestSchedule(t *testing.T) { | |
sheet := grid.CSV(scheduleFile) | |
// This test represents a parser for Innopolis University schedule for BS4 | |
// students in 2023 winter/spring semester. | |
// Thanks to the university for giving an idea of this library, as this | |
// schedule is a perfect example of a shit-like data that is hard to parse. | |
// Lesson represents a single lesson. | |
// Here anchor is placed on the 'LessonName' cell, all positions in tags are relative | |
// to the anchor. | |
// | |
// Lesson itself is represented in the following way in the table: | |
// 09:30-11:00 | ... | LessonName | | |
// | ... | Teachers | | |
// | ... | Room | | |
type Lesson struct { | |
Name string `grid:"row:0,col:0"` | |
Teachers string `grid:"row:1,col:0"` | |
Room string `grid:"row:2,col:0"` | |
Span timeSpan `grid:"row:0,col:$1"` // time span is always on the first column | |
} | |
dec := gctrl.NewDecoder( | |
// groups | |
gctrl.RepeatCols{ | |
// decoding starts from 0,0, so relative position to origin is the same as absolute in here | |
From: grid.RelativePos{Row: 1, Col: 1}, | |
Until: gctrl.EOF, | |
Key: gctrl.Value{At: grid.RelativePos{Row: 0, Col: 0}}, | |
// weekdays | |
Nested: gctrl.RepeatCols{ | |
From: grid.RelativePos{Row: +1, Col: -1}, | |
Until: gctrl.EOF, | |
Key: gctrl.Value{At: grid.RelativePos{Row: 0, Col: 0}}, | |
// lessons | |
Nested: gctrl.RepeatRows{ | |
From: grid.RelativePos{Row: +1, Col: +1}, | |
Until: gctrl.Value{ | |
At: grid.RelativePos{Row: 0, Col: -1}, | |
Matches: regexp.MustCompile(`MONDAY|TUESDAY|WEDNESDAY|THURSDAY|FRIDAY|SATURDAY|SUNDAY`), | |
}, | |
Into: (*Lesson)(nil), | |
}, | |
}, | |
}, | |
) | |
var schedule map[string]map[string][]Lesson | |
err := dec.Decode(sheet, &schedule) | |
require.NoError(t, err) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment