diff --git a/main.go b/main.go index 2cc4c0c..7971a63 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,11 @@ package main import ( "encoding/json" "fmt" + "math/rand" "os" "path/filepath" "slices" + "sort" "strconv" "strings" "time" @@ -142,15 +144,21 @@ type JumpDatabaseMapEntry struct { } `json:"zones"` } +type PreviousRun struct { + Duration float64 `json:"duration"` + Date float64 `json:"date"` +} + type JumpmapRunTimeEntry struct { - Nontempusrun bool `json:"nontempusrun"` - ManuallyCreated bool `json:"manually_created"` - ID int `json:"id"` - Duration float64 `json:"duration"` - Rank int `json:"rank"` - Date float64 `json:"date"` - Class string `json:"class"` - Name string `json:"name"` + Nontempusrun bool `json:"nontempusrun"` + ManuallyCreated bool `json:"manually_created"` + ID int `json:"id"` + Duration float64 `json:"duration"` + Rank int `json:"rank"` + Date float64 `json:"date"` + Class string `json:"class"` + Name string `json:"name"` + PreviousRuns []PreviousRun `json:"previous_runs"` } func check(e error) { @@ -159,6 +167,26 @@ func check(e error) { } } +func CreateBaseRunTimeEntry(jump_map_name string) JumpmapRunTimeEntry { + base_entry_str := `{ + "nontempusrun": true, + "manually_created": true, + "id": -1, + "duration": 0, + "rank": -1, + "date": 0, + "class": "SOLDIER", + "name": "jump_basejson" +}` + + var jump_map JumpmapRunTimeEntry + if err := json.Unmarshal([]byte(base_entry_str), &jump_map); err != nil { + check(err) + } + jump_map.Name = jump_map_name + return jump_map +} + func ConvertPrettyTimeToSeconds(time string) float64 { parts := strings.Split(time, ":") seconds := 0.0 @@ -201,6 +229,13 @@ func ExtractBareFilenameFromPath(in_path string) string { return append(slice[:s], slice[s+1:]...) }*/ +func GetCurtime() float64 { + currentTime := time.Now() + fractional_nanosecond := float64(currentTime.UnixNano()) + unix_seconds := fractional_nanosecond / 1e9 + return unix_seconds +} + const ( JumpmapTypeSoldier = 0 JumpmapTypeDemoman = 1 @@ -234,8 +269,16 @@ func StringToJumpmapRunType(jump_map_wanted_type string) int { var mapinfo_database_location = filepath.Join("database", "map_info") +func GetDatabaseFilePath(jump_map_name string) string { + return filepath.Join(mapinfo_database_location, jump_map_name+".json") +} + +func GetRecordFilePath(jump_map_type int, jump_map_name string) string { + return filepath.Join("personal", "completed."+GetFileNameFromJumpmapRunTypeEnum(jump_map_type), jump_map_name+".json") +} + func ReadDatabaseFile(jump_map_name string) JumpDatabaseMapEntry { - data, error := os.ReadFile(filepath.Join(mapinfo_database_location, jump_map_name+".json")) + data, error := os.ReadFile(GetDatabaseFilePath(jump_map_name)) check(error) var jump_map JumpDatabaseMapEntry @@ -243,11 +286,15 @@ func ReadDatabaseFile(jump_map_name string) JumpDatabaseMapEntry { check(err) } + if jump_map.Name != ExtractBareFilenameFromPath(jump_map_name) { + panic("Malformed Map Database entry: " + jump_map_name + " Has: " + jump_map.Name) + } + return jump_map } func ReadRunRecordFile(jump_map_type int, jump_map_name string) JumpmapRunTimeEntry { - data, error := os.ReadFile(filepath.Join("personal", "completed."+GetFileNameFromJumpmapRunTypeEnum(jump_map_type), jump_map_name+".json")) + data, error := os.ReadFile(GetRecordFilePath(jump_map_type, jump_map_name)) check(error) var jump_map JumpmapRunTimeEntry @@ -255,26 +302,85 @@ func ReadRunRecordFile(jump_map_type int, jump_map_name string) JumpmapRunTimeEn check(err) } + if jump_map.Name != ExtractBareFilenameFromPath(jump_map_name) { + panic("Malformed Run Record: " + jump_map_name + " Has: " + jump_map.Name) + } + return jump_map } +func SubmitNewTime(jump_map_type int, jump_map_name string, duration float64) { + record_filepath := GetRecordFilePath(jump_map_type, jump_map_name) + + var new_entry JumpmapRunTimeEntry + // Try to read the file firs + _, err := os.Stat(record_filepath) + run_exists := err == nil + if run_exists { + // if it exists, read it and verify run is fast + new_entry = ReadRunRecordFile(jump_map_type, jump_map_name) + if duration >= new_entry.Duration { + if new_entry.Duration == duration { + fmt.Printf("Time is duplicate or the same as current time: %f - %s\n", new_entry.Duration, jump_map_name+": "+GetPrettyTime(new_entry.Duration)) + } else { + how_slow := (new_entry.Duration - duration) + fmt.Printf("Time is too slow by %f seconds: %s\n", how_slow, jump_map_name) + fmt.Printf("Get Faster by: %s\n", GetPrettyTime(how_slow)) + } + panic("Time too slow!!! Get faster then try again.") + } + + // back it up + ConvertRunToPrevious := func(new_entry JumpmapRunTimeEntry) PreviousRun { + var prev_run PreviousRun + prev_run.Date = new_entry.Date + prev_run.Duration = new_entry.Duration + return prev_run + } + new_entry.PreviousRuns = append(new_entry.PreviousRuns, ConvertRunToPrevious(new_entry)) + + // Create a fresh database entry + } else { + new_entry = CreateBaseRunTimeEntry(jump_map_name) + } + + // Set the time within the record + new_entry.Duration = duration + new_entry.Date = GetCurtime() + + // Assemble and Write it to a file + json_file_data, err := json.MarshalIndent(new_entry, "", "\t") + check(err) + err = os.WriteFile(record_filepath, json_file_data, 0777) + check(err) + + fmt.Println("Submitted NEW time for map: " + jump_map_name) +} + func PrintRecord(printable_record any) string { data, error := json.MarshalIndent(printable_record, "", "\t") check(error) return string(data) } +func DoesFileExist(filepath string) bool { + if _, err := os.Stat(filepath); err == nil { + return true + } + return false +} + func FindMapNameFromPartial(partial_jump_map_name string) string { - if !strings.HasPrefix(partial_jump_map_name, "jump_") { + if !strings.HasPrefix(partial_jump_map_name, "jump_") && !strings.HasPrefix(partial_jump_map_name, "rj_") { partial_jump_map_name = "jump_" + partial_jump_map_name } - found_files, err := filepath.Glob(filepath.Join(mapinfo_database_location, partial_jump_map_name+"*.json")) + found_files, err := filepath.Glob(GetDatabaseFilePath(partial_jump_map_name + "*")) check(err) found_file_count := len(found_files) if found_file_count > 1 { - found_map := filepath.Join(filepath.Join(mapinfo_database_location, partial_jump_map_name+".json")) - if _, err := os.Stat(found_map); err == nil { + found_map := GetDatabaseFilePath(partial_jump_map_name) + if DoesFileExist(found_map) { return ExtractBareFilenameFromPath(found_map) } else { fmt.Printf("There are too many maps that match your request: \"%s\"\n", partial_jump_map_name) @@ -285,18 +391,27 @@ func FindMapNameFromPartial(partial_jump_map_name string) string { os.Exit(2) } } + if len(found_files) == 0 { + fmt.Println("Unable to find mapname: " + partial_jump_map_name) + panic("Attempting to find map that doesnt exist: " + partial_jump_map_name) + } + // should be just one return ExtractBareFilenameFromPath(found_files[0]) } -func GetPrettyMapTime(jump_map_type int, jump_map_name string) string { - run_record := ReadRunRecordFile(jump_map_type, jump_map_name) - duration := time.Duration(run_record.Duration) * time.Second +func GetPrettyTime(in_time float64) string { + duration := time.Duration(in_time) * time.Second hours := int(duration.Hours()) minutes := int(duration.Minutes()) % 60 seconds := int(duration.Seconds()) % 60 return fmt.Sprintf("%dh %dm %ds", hours, minutes, seconds) } +func GetPrettyMapTime(jump_map_type int, jump_map_name string) string { + run_record := ReadRunRecordFile(jump_map_type, jump_map_name) + return GetPrettyTime(run_record.Duration) +} + func GetMapList() []string { found_files, err := filepath.Glob(filepath.Join(mapinfo_database_location, "*.json")) check(err) @@ -337,28 +452,55 @@ func IsOnMapIgnorelist(jump_map_name string) bool { return false } -func PrintMapUsageInfo() { - fmt.Println("usage: " + os.Args[0] + "[operation] ") +func PrintMapRuntime(jump_map_type int, jump_map_name string) { + fmt.Println("Run time for " + jump_map_name + ": " + GetPrettyMapTime(jump_map_type, jump_map_name)) } -/*func PrintClassUsageInfo() { -fmt.Println("usage: " + os.Args[0] + "[operation] ") -}*/ - func PrintUsageInfo() { fmt.Println("usage: " + os.Args[0] + " [operation] ") fmt.Println("try running \"" + os.Args[0] + " help\" for additional info on operations") } +func PrintMapUsageInfo() { + fmt.Println("usage: " + os.Args[0] + " [operation] ") +} + +func PrintClassUsageInfo() { + fmt.Println("usage: " + os.Args[0] + " [operation] ") +} + +func PrintSubmitTimeInfo() { + fmt.Println("usage: " + os.Args[0] + " [operation]