Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v0.9.2 162 lines 3.2 kB view raw
1package model 2 3import ( 4 "database/sql" 5 "encoding/json" 6 "fmt" 7 "math" 8 "time" 9 10 "github.com/google/uuid" 11 "gorm.io/datatypes" 12) 13 14type PlayerEventAPI struct { 15 ID string `json:"id"` 16 Time time.Time `json:"time"` 17 PlayerID string `json:"playerId"` 18 EventType string `json:"eventType"` 19 Meta map[string]any `json:"meta"` 20} 21 22type PlayerEvent struct { 23 ID string `gorm:"primarykey"` 24 Time time.Time 25 PlayerID string `gorm:"index"` 26 EventType string 27 Meta datatypes.JSON 28} 29 30func MaybeNull(s string) sql.NullString { 31 if s == "" { 32 return sql.NullString{Valid: false} 33 } 34 return sql.NullString{Valid: true, String: s} 35} 36 37func (m *DBModel) CreatePlayerEvent(event PlayerEventAPI) error { 38 uu, err := uuid.NewV7() 39 if err != nil { 40 return err 41 } 42 metaBs, err := json.Marshal(event.Meta) 43 if err != nil { 44 return err 45 } 46 err = m.DB.Model(PlayerEvent{}).Create(PlayerEvent{ 47 ID: uu.String(), 48 Time: event.Time, 49 PlayerID: event.PlayerID, 50 EventType: event.EventType, 51 Meta: datatypes.JSON(metaBs), 52 }).Error 53 if err != nil { 54 return err 55 } 56 return nil 57} 58 59func (m *DBModel) ListPlayerEvents(playerID string) ([]PlayerEvent, error) { 60 events := []PlayerEvent{} 61 // err := m.DB.Find(&events).Error 62 err := m.DB.Where("player_id = ?", playerID).Find(&events).Error 63 if err != nil { 64 return nil, fmt.Errorf("error retrieving player events: %w", err) 65 } 66 return events, nil 67} 68 69func (m *DBModel) PlayerReport(playerID string) (map[string]any, error) { 70 events, err := m.ListPlayerEvents(playerID) 71 if err != nil { 72 return nil, err 73 } 74 whatHappenedReport := map[string]float64{} 75 retries := 0 76 for _, e := range events { 77 if e.EventType == "retry" { 78 retries++ 79 continue 80 } 81 if e.EventType != "aq-played" { 82 continue 83 } 84 bs, err := e.Meta.MarshalJSON() 85 if err != nil { 86 return nil, err 87 } 88 meta := map[string]any{} 89 err = json.Unmarshal(bs, &meta) 90 if err != nil { 91 return nil, err 92 } 93 whatHappenedAny, ok := meta["whatHappened"] 94 if !ok { 95 continue 96 } 97 whatHappened, ok := whatHappenedAny.(map[string]any) 98 if !ok { 99 continue 100 } 101 for state, time := range whatHappened { 102 ms, ok := time.(float64) 103 if ok { 104 whatHappenedReport[state] = whatHappenedReport[state] + ms 105 } 106 } 107 } 108 109 avSyncs := []float64{} 110 for _, e := range events { 111 if e.EventType != "av-sync" { 112 continue 113 } 114 bs, err := e.Meta.MarshalJSON() 115 if err != nil { 116 return nil, err 117 } 118 meta := map[string]any{} 119 err = json.Unmarshal(bs, &meta) 120 if err != nil { 121 return nil, err 122 } 123 diff, ok := meta["diff"].(float64) 124 if !ok { 125 continue 126 } 127 avSyncs = append(avSyncs, diff) 128 } 129 130 report := map[string]any{ 131 "whatHappened": whatHappenedReport, 132 } 133 134 if len(avSyncs) > 0 { 135 min := math.Inf(1) 136 max := math.Inf(-1) 137 sum := 0.0 138 for _, sync := range avSyncs { 139 if sync < min { 140 min = sync 141 } 142 if sync > max { 143 max = sync 144 } 145 sum += sync 146 } 147 avg := sum / float64(len(avSyncs)) 148 report["avSync"] = map[string]float64{ 149 "min": min, 150 "max": max, 151 "avg": avg, 152 } 153 } 154 155 report["retries"] = retries 156 157 return report, nil 158} 159 160func (m *DBModel) ClearPlayerEvents() error { 161 return m.DB.Where("1 = 1").Delete(&PlayerEvent{}).Error 162}