From 3f7f858d0360a56a94212dec33f8029d55c2e5d6 Mon Sep 17 00:00:00 2001 From: Tracreed Date: Wed, 31 Jan 2018 11:19:15 +0100 Subject: [PATCH] Stuff --- compareID.go | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 compareID.go diff --git a/compareID.go b/compareID.go new file mode 100644 index 0000000..126b6f1 --- /dev/null +++ b/compareID.go @@ -0,0 +1,180 @@ +package compareID + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/agext/levenshtein" + "io/ioutil" + "net/http" + "strings" + "time" +) + +//Anime contains the essentials for being able to compare anidb to meikan +type Anime struct { + ID int + Type string + Episodes int + Title string + StartDate time.Time + EndDate time.Time +} + +//Result is the way the json received is structured +//It contains a collection of animes made up of AnimeRes +type Result struct { + Total int `json:"total"` + Anime []AnimeRes `json:"data"` +} + +//AnimeRes is how the search results from meikan are built up in the JSON +type AnimeRes struct { + EndDate string `json:"end_date"` + Episodes int `json:"episodes"` + ID int `json:"id"` + Rating string `json:"rating"` + StartDate string `json:"start_date"` + State string `json:"state"` + Title string `json:"title"` + Type string `json:"type"` +} + +//Animes is a collection of animes +type Animes []MatchedAnime + +//MatchedAnime contains all the neccessary information after matching two animes +type MatchedAnime struct { + MeikanTitle string + AnidbTitle string + MeikanID int + AnidbID int + Score int +} + +//check does a default error check +func check(e error) { + if e != nil { + panic(e) + } +} + +//lessType makes types when comparing less specific +//So missmatches like OVA == Specials don't happen. +func LessType(Type string) string { + switch Type { + case "TV", "ONA": + return "Shows" + case "OVA", "Specials": + return "Extra" + } + + return Type +} + +//fixType changes the types anidb uses to ones that match with meikan specifications. +func FixType(Type string) string { + switch Type { + case "TV Series": + return "TV" + case "TV Special": + return "Special" + case "Web": + return "ONA" + } + return Type +} + +//fixMeikanDates takes two strings and tries to parse them returning two Time structs +func FixMeikanDates(Date, Date2 string) (date, date2 time.Time) { + if Date != "" { + date, _ = time.Parse(`2006-01-02`, Date) + } + if Date2 != "" { + date2, _ = time.Parse(`2006-01-02`, Date) + } + return date, date2 +} + +//subAnimeDates subtracts one date from the other. +//Returning an integer that is added onto the total score when comparing. +func SubAnimeDates(Date, Date2 time.Time) (total int) { + if Date.Year() == 1 && Date2.Year() == 1 { + return 0 + } + diff := Date.Sub(Date2) + if diff < 0 { + diff = diff * -1 + } + if diff <= 2190*time.Hour { + return 50 + } + return -150 +} + +//checkResults takes an Anime struct and a channel. +//It compares the supplied anime to all the search results returned from searching the title. +//If the score is over 100 it should be a match. +func CheckResults(anime Anime, c chan MatchedAnime) { + fmt.Println(`Searching anime`, anime.ID) + var highest, hI int + var err error + anime.Title = strings.Replace(strings.Replace(anime.Title, `\`, `\\`, -1), `"`, `\"`, -1) + var search = bytes.NewBuffer([]byte(`{"title":"` + anime.Title + `", "show_r18": true}`)) + resp, err := http.Post("https://api.meikan.moe/v1/anime?incl=start_date,end_date", "application/json", search) + check(err) + fmt.Println(`Completed meikan search for`, anime.ID) + // nolint: errcheck + defer resp.Body.Close() + var result Result + body, err := ioutil.ReadAll(resp.Body) + check(err) + _ = json.NewDecoder(bytes.NewReader(body)).Decode(&result) + anime.Type = FixType(anime.Type) + if anime.Episodes < 1 { + anime.Episodes = 1 + } + for i := 0; i < len(result.Anime); i++ { + var total int + meikan := result.Anime[i] + stDate, enDate := FixMeikanDates(meikan.StartDate, meikan.EndDate) + if meikan.Type == anime.Type { + total += 25 + } else { + MType := LessType(meikan.Type) + AType := LessType(anime.Type) + if MType == AType { + total += 12 + } + } + score := levenshtein.Match(meikan.Title, anime.Title, nil) + if score > 0.95 { + total += 50 + } + if meikan.Episodes == anime.Episodes { + total += 25 + } + total += SubAnimeDates(stDate, anime.StartDate) + if anime.Episodes != 1 { + total += SubAnimeDates(enDate, anime.EndDate) + } + if total > highest { + highest = total + hI = i + } + } + //return highest, hI + if len(result.Anime) != 0 { + c <- MatchedAnime{ + MeikanTitle: result.Anime[hI].Title, + AnidbTitle: anime.Title, + MeikanID: result.Anime[hI].ID, + AnidbID: anime.ID, + Score: highest, + } + } +} + +func main() { + http.DefaultTransport = &http.Transport{MaxIdleConnsPerHost: 50, MaxIdleConns: 50} +}