Skip to content

Instantly share code, notes, and snippets.

@Semior001
Last active February 7, 2023 22:15
Show Gist options
  • Save Semior001/c30baa51386b748a84bb33f4139e602a to your computer and use it in GitHub Desktop.
Save Semior001/c30baa51386b748a84bb33f4139e602a to your computer and use it in GitHub Desktop.
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