Skip to content

Commit

Permalink
Merge pull request #28 from iomz/feat-conjunct-rule-matching
Browse files Browse the repository at this point in the history
feat: make the rule criteria conjuct with each other
  • Loading branch information
iomz authored Jun 28, 2023
2 parents 1325db3 + 440db5f commit fd78d66
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 60 deletions.
4 changes: 4 additions & 0 deletions asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import (
)

var (
// Base64FullKey holds the /assets/flutter_assets/assets/key/android.jpg in the v8 APK
//go:embed assets/base64-full.key
Base64FullKey embed.FS
// CoordinatesJSON is a JSON contains the base GPS locations
//go:embed assets/coordinates.json
CoordinatesJSON embed.FS
// RegionsJSON is a JSON contains the region mapping
//go:embed assets/regions.json
RegionsJSON embed.FS
// VersionsJSON is a JSON contains the valid SDK versions
//go:embed assets/versions.json
VersionsJSON embed.FS
)
Expand Down
2 changes: 1 addition & 1 deletion asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestNewAsset(t *testing.T) {
areaCount := 0
for region := range asset.Regions {
for range asset.Regions[region] {
areaCount += 1
areaCount++
}
}
if areaCount != nAreas {
Expand Down
2 changes: 1 addition & 1 deletion cmd/radicron/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func run(wg *sync.WaitGroup, configFileName string) {
// check each program
for _, p := range weeklyPrograms {
if rules.HasMatch(stationID, p) {
err = radicron.Download(wg, ctx, p)
err = radicron.Download(ctx, wg, p)
if err != nil {
log.Printf("downlod faild: %s", err)
}
Expand Down
6 changes: 3 additions & 3 deletions download.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import (
var sem = make(chan struct{}, MaxConcurrency)

func Download(
wg *sync.WaitGroup,
ctx context.Context,
wg *sync.WaitGroup,
prog *Prog,
) (err error) {
asset := GetAsset(ctx)
Expand Down Expand Up @@ -91,7 +91,7 @@ func Download(
log.Printf("start downloading [%s]%s (%s): %s", prog.StationID, title, start, uri)
prog.M3U8 = uri
wg.Add(1)
go downloadProgram(wg, ctx, prog, output)
go downloadProgram(ctx, wg, prog, output)
return nil
}

Expand Down Expand Up @@ -171,8 +171,8 @@ func downloadLink(link, output string) error {
// downloadProgram manages the download for the given program
// in a go routine and notify the wg when finished
func downloadProgram(
wg *sync.WaitGroup, // the wg to notify
ctx context.Context, // the context for the request
wg *sync.WaitGroup, // the wg to notify
prog *Prog, // the program metadata
output *radigo.OutputConfig, // the file configuration
) {
Expand Down
2 changes: 1 addition & 1 deletion region_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestFetchXMLRegion(t *testing.T) {
for _, stations := range region.Region {
for _, station := range stations.Stations {
t.Logf("%v (%v) %v\n", stations.RegionID, station.AreaID, station.Name)
stationCount += 1
stationCount++
}
}
if stationCount < nStations {
Expand Down
147 changes: 93 additions & 54 deletions rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ type Rule struct {
// Match returns true if the rule matches the program
// 1. check the Window filter
// 2. check the DoW filter
// 3. check the StationID filter
// TODO: reduce the complexity
func (r *Rule) Match(stationID string, p *Prog) bool { //nolint:gocyclo
// 3. check the StationID
// 4. match the criteria
func (r *Rule) Match(stationID string, p *Prog) bool {
// 1. check Window
if r.HasWindow() {
startTime, err := time.ParseInLocation(DatetimeLayout, p.Ft, Location)
Expand All @@ -67,61 +67,19 @@ func (r *Rule) Match(stationID string, p *Prog) bool { //nolint:gocyclo
return false // skip before the fetch window
}
}
// 2. check DoW
if r.HasDoW() {
dow := map[string]time.Weekday{
"sun": time.Sunday,
"mon": time.Monday,
"tue": time.Tuesday,
"wed": time.Wednesday,
"thu": time.Thursday,
"fri": time.Friday,
"sat": time.Saturday,
}
st, _ := time.ParseInLocation(DatetimeLayout, p.Ft, Location)
dowMatch := false
for _, d := range r.DoW {
if st.Weekday() == dow[strings.ToLower(d)] {
dowMatch = true
}
}
if !dowMatch {
return false
}
// 2. check dow
if !r.MatchDoW(p.Ft) {
return false
}
// 3. check StationID
if r.HasStationID() && r.StationID != stationID {
return false // skip mismatching rules for stationID
// 3. check station-id
if !r.MatchStationID(stationID) {
return false
}
// 4. Match
if r.HasTitle() && strings.Contains(p.Title, r.Title) {
log.Printf("rule[%s] matched with title: '%s'", r.Name, p.Title)
return true
} else if r.HasPfm() && strings.Contains(p.Pfm, r.Pfm) {
log.Printf("rule[%s] matched with pfm: '%s'", r.Name, p.Pfm)

// 4. match
if r.MatchPfm(p.Pfm) && r.MatchTitle(p.Title) && r.MatchKeyword(p) {
return true
} else if r.HasKeyword() {
if strings.Contains(p.Title, r.Keyword) {
log.Printf("rule[%s] matched with title: '%s'", r.Name, p.Title)
return true
} else if strings.Contains(p.Pfm, r.Keyword) {
log.Printf("rule[%s] matched with pfm: '%s'", r.Name, p.Pfm)
return true
} else if strings.Contains(p.Info, r.Keyword) {
log.Printf("rule[%s] matched with info: \n%s", r.Name, strings.ReplaceAll(p.Info, "\n", ""))
return true
} else if strings.Contains(p.Desc, r.Keyword) {
log.Printf("rule[%s] matched with desc: '%s'", r.Name, strings.ReplaceAll(p.Desc, "\n", ""))
return true
}
for _, tag := range p.Tags {
if strings.Contains(tag, r.Keyword) {
log.Printf("rule[%s] matched with tag: '%s'", r.Name, tag)
return true
}
}
}
// both title and keyword are empty or not found
return false
}

Expand Down Expand Up @@ -153,6 +111,87 @@ func (r *Rule) HasWindow() bool {
return r.Window != ""
}

func (r *Rule) MatchDoW(ft string) bool {
if !r.HasDoW() {
return true
}
dow := map[string]time.Weekday{
"sun": time.Sunday,
"mon": time.Monday,
"tue": time.Tuesday,
"wed": time.Wednesday,
"thu": time.Thursday,
"fri": time.Friday,
"sat": time.Saturday,
}
st, _ := time.ParseInLocation(DatetimeLayout, ft, Location)
for _, d := range r.DoW {
if st.Weekday() == dow[strings.ToLower(d)] {
return true
}
}
return false
}

func (r *Rule) MatchKeyword(p *Prog) bool {
if !r.HasKeyword() {
return true // if no keyward, match all
}

if strings.Contains(p.Title, r.Keyword) {
log.Printf("rule[%s] matched with title: '%s'", r.Name, p.Title)
return true
} else if strings.Contains(p.Pfm, r.Keyword) {
log.Printf("rule[%s] matched with pfm: '%s'", r.Name, p.Pfm)
return true
} else if strings.Contains(p.Info, r.Keyword) {
log.Printf("rule[%s] matched with info: \n%s", r.Name, strings.ReplaceAll(p.Info, "\n", ""))
return true
} else if strings.Contains(p.Desc, r.Keyword) {
log.Printf("rule[%s] matched with desc: '%s'", r.Name, strings.ReplaceAll(p.Desc, "\n", ""))
return true
}
for _, tag := range p.Tags {
if strings.Contains(tag, r.Keyword) {
log.Printf("rule[%s] matched with tag: '%s'", r.Name, tag)
return true
}
}
return false
}

func (r *Rule) MatchPfm(pfm string) bool {
if !r.HasPfm() {
return true // if no pfm, match all
}
if strings.Contains(pfm, r.Pfm) {
log.Printf("rule[%s] matched with pfm: '%s'", r.Name, pfm)
return true
}
return false
}

func (r *Rule) MatchStationID(stationID string) bool {
if !r.HasStationID() {
return true // if no station-id, match all
}
if r.StationID == stationID {
return true
}
return false
}

func (r *Rule) MatchTitle(title string) bool {
if !r.HasTitle() {
return true // if not title, match all
}
if strings.Contains(title, r.Title) {
log.Printf("rule[%s] matched with title: '%s'", r.Name, title)
return true
}
return false
}

func (r *Rule) SetName(name string) {
r.Name = name
}
Loading

0 comments on commit fd78d66

Please sign in to comment.