// Sort chronologically sorts a resume's work and volunteer experience items. func (rsm *Resume) Sort() { slice.Sort(rsm.Work, func(i, j int) bool { return rsm.Work[i].StartDate.Before(rsm.Work[j].StartDate.Time) }) slice.Sort(rsm.Volunteer, func(i, j int) bool { return rsm.Volunteer[i].StartDate.Before(rsm.Volunteer[j].StartDate.Time) }) }
func GetNotification(c web.C, w http.ResponseWriter, r *http.Request) { var token = r.FormValue("token") var userId int //init my empty struct who contains an array string for login user notifs := Notifications{} //check if token exist if CheckToken(token, w) == false { return } //check if token matches with an user Id if userId = GetUserIdWithToken(token, w); userId == -1 { return } a := MyAppend(GetMessageNotification(userId), GetLikeNotification(userId)) notifs.Notif = MyAppend(a, GetVisiteNotification(userId)) slice.Sort(notifs.Notif[:], func(i, j int) bool { if strings.Compare(notifs.Notif[i].CreateAt, notifs.Notif[j].CreateAt) > 0 { return true } else { return false } }) notifs.Status = "OK" go MakeNotifAsRead(userId) RenderJSON(w, notifs, http.StatusOK) }
func makeChart(r opentsdb.ResponseSet, m_units map[string]string) ([]*chartSeries, error) { var series []*chartSeries for _, resp := range r { dps := make([][2]float64, 0) for k, v := range resp.DPS { ki, err := strconv.ParseInt(k, 10, 64) if err != nil { return nil, err } dps = append(dps, [2]float64{float64(ki), float64(v)}) } if len(dps) > 0 { slice.Sort(dps, func(i, j int) bool { return dps[i][0] < dps[j][0] }) name := resp.Metric if len(resp.Tags) > 0 { name += resp.Tags.String() } series = append(series, &chartSeries{ Name: name, Metric: resp.Metric, Tags: resp.Tags, Data: dps, Unit: m_units[resp.Metric], }) } } return series, nil }
// SortByCounter sorts the list by the counter of the word func (digester *Digester) SortByCounter(order string) { data := digester.GetData() slice.Sort(data, func(i, j int) bool { if order == "ASC" { return data[i].GetCounter() <= data[j].GetCounter() } return data[i].GetCounter() > data[j].GetCounter() }) }
func BenchmarkIntSlice(b *testing.B) { s := make([]int, len(intdata)) b.ResetTimer() for i := 0; i < b.N; i++ { copy(s, intdata) slice.Sort(s, func(i, j int) bool { return s[i] > s[j] }) } }
func BenchmarkStringSlice(b *testing.B) { s := make([]string, len(strdata)) b.ResetTimer() for i := 0; i < b.N; i++ { copy(s, strdata) slice.Sort(s, func(i, j int) bool { return s[i] > s[j] }) } }
func (r Route) String() string { rt := []string{} for _, part := range r.parts { rt = append(rt, part.String()) } slice.Sort(rt, func(i, j int) bool { return rt[i] < rt[j] }) return fmt.Sprintf("Route(%s)", strings.Join(rt, " && ")) }
func (notification *Notification) getLastNotification() SimpleNotificationList { v := GroupedList{} ret := SimpleNotificationList{} lastWeek := time.Now().AddDate(0, 0, -7) //Get from database all notification between now and a week ago, we group them by type and IdLink curs, _ := r.Table("notifications"). Filter(r.Row.Field("UserId").Eq(notification.user.Id)). Filter(r.Row.Field("CreatedAt").Gt(lastWeek)). OrderBy("-CreatedAt"). Group("Type", "IdLink"). Run(api.Sess) curs.All(&v.List) //We sort all notification to avoid had identic notifications. var arraySimpleNotification []SimpleNotification for _, group := range v.List { simple := SimpleNotification{ Type: group.Group[0].(string), IdLink: group.Group[1].(string), Read: true, } var create time.Time var index = -1 for j, notif := range group.Reduction { if notif.Read == false { simple.Read = false } if create.Before(notif.CreatedAt) == true { create = notif.CreatedAt index = j } } simple.CreatedAt = create simple.Name = group.Reduction[index].Name simple.Others = len(group.Reduction) - 1 arraySimpleNotification = append(arraySimpleNotification, simple) } //Sort by createDate slice.Sort(arraySimpleNotification[:], func(i, j int) bool { return arraySimpleNotification[i].CreatedAt.After(arraySimpleNotification[j].CreatedAt) }) ret.List = arraySimpleNotification return ret }
func cmdSummary(d db.DB, periodS, firstDayS string) { period, err := datetime.ParsePeriod(periodS) if err != nil { fatal(err) } firstDay, err := datetime.ParseWeekday(firstDayS) if err != nil { fatal(err) } categories, err := d.Categories() if err != nil { fatal(err) } itr, err := NewSummaryIterator(d, period, firstDay, time.Now()) if err != nil { fatal(err) } defer itr.Close() for { if summary, err := itr.Next(); err == io.EOF { break } else if err != nil { fatal(err) } else { fmt.Printf("%s\n\n", PeriodHeadline(summary.From, summary.To, period)) names := make(map[string]string) order := make([]string, 0, len(summary.Categories)) for id, _ := range summary.Categories { names[id] = FormatCategory(categories.Path(id)) order = append(order, id) } slice.Sort(order, func(i, j int) bool { return summary.Categories[order[i]] > summary.Categories[order[j]] }) t := table.New().Padding(" ") for _, id := range order { d := FormatDuration(summary.Categories[id]) t.Add(table.String(names[id]), table.String(d).Align(table.Right)) } fmt.Printf("%s\n", Indent(t.String(), " ")) } } }
// Available return the migrations in the environment's directory sorted in // ascending lexicographic order. func (s Service) Available() ([]*Migration, error) { files, _ := filepath.Glob(filepath.Join(s.env.Directory, "*.sql")) // The only possible error here is a pattern error var migrations []*Migration for _, file := range files { migration, err := NewMigration(file) if err != nil { return nil, err } migrations = append(migrations, migration) } slice.Sort(migrations, func(i, j int) bool { return migrations[i].Name < migrations[j].Name }) return migrations, nil }
// Tree returns the root node of the category tree. func (c CategoryMap) Root() *CategoryNode { index := map[string]*CategoryNode{"": &CategoryNode{}} for _, category := range c { parent := index[category.ParentID] if parent == nil { parent = &CategoryNode{} index[category.ParentID] = parent } node := index[category.ID] if node == nil { node = &CategoryNode{} index[category.ID] = node } node.Category = category parent.Children = append(parent.Children, node) slice.Sort(parent.Children, func(i, j int) bool { return parent.Children[i].Name < parent.Children[j].Name }) } return index[""] }
func (s *Schedule) ExprGraph(t miniprofiler.Timer, unit string, res []*expr.Result) (chart.Chart, error) { c := chart.ScatterChart{ Key: chart.Key{Pos: "itl"}, YRange: chart.Range{Label: unit}, } c.XRange.Time = true for ri, r := range res { rv := r.Value.(expr.Series) pts := make([]chart.EPoint, len(rv)) idx := 0 for k, v := range rv { pts[idx].X = float64(k.Unix()) pts[idx].Y = v idx++ } slice.Sort(pts, func(i, j int) bool { return pts[i].X < pts[j].X }) c.AddData(r.Group.String(), pts, chart.PlotStyleLinesPoints, Autostyle(ri)) } return &c, nil }
// Applied return the migrations in the environment's directory that are marked // as applied in the database sorted in ascending lexicographic order. func (s Service) Applied() ([]*Migration, error) { files, err := s.conn.GetApplied() if err != nil { return nil, err } var migrations []*Migration for _, file := range files { migration, err := NewMigration(filepath.Join(s.env.Directory, file)) if err != nil { return nil, err } migrations = append(migrations, migration) } slice.Sort(migrations, func(i, j int) bool { return migrations[i].Name < migrations[j].Name }) return migrations, nil }
// GET /points/nearest?lat=*&lng=*&dist=_ func getNearestPoints(w http.ResponseWriter, r *http.Request) { badRequestError := Response{"error", 400, "Bad Request", nil} params := r.URL.Query() lat, err1 := strconv.ParseFloat(params.Get("lat"), 64) lng, err2 := strconv.ParseFloat(params.Get("lng"), 64) if err1 != nil || err2 != nil { routes.ServeJson(w, badRequestError) return } maxDistance := float64(50) if d, err := strconv.ParseFloat(params.Get("dist"), 32); err == nil { maxDistance = d } currentPoint := geo.NewPoint(lat, lng) var p Point result := make([]distanceRecord, 0) iter := Points.Find(bson.M{}).Iter() for iter.Next(&p) { lat, _ := strconv.ParseFloat(p.Latitude, 64) lng, _ := strconv.ParseFloat(p.Longitude, 64) point := geo.NewPoint(lat, lng) distance := currentPoint.GreatCircleDistance(point) * 1000 if distance <= maxDistance { result = append(result, distanceRecord{p.Id, distance}) } } slice.Sort(result, func(i, j int) bool { return result[i].Distance < result[j].Distance }) routes.ServeJson(w, result) }
func GatherStats(config models.Configuration) (stats []models.Status) { stats = []models.Status{} for _, server := range config.Servers { pingSuccess := testPing(server.Hostname, false, config) var httpSuccess bool if server.Url != "" { httpSuccess = testHttp(server.Url, config) } status := models.Status{ Name: server.Name, HttpPresent: server.Url != "", HttpSuccess: httpSuccess, PingSuccess: pingSuccess, Created: time.Now(), } stats = append(stats, status) } slice.Sort(stats[:], func(i, j int) bool { return stats[i].Name < stats[j].Name }) return stats }
// Graph takes an OpenTSDB request data structure and queries OpenTSDB. Use the // json parameter to pass JSON. Use the b64 parameter to pass base64-encoded // JSON. func Graph(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) { j := []byte(r.FormValue("json")) if bs := r.FormValue("b64"); bs != "" { b, err := base64.StdEncoding.DecodeString(bs) if err != nil { return nil, err } j = b } if len(j) == 0 { return nil, fmt.Errorf("either json or b64 required") } oreq, err := opentsdb.RequestFromJSON(j) if err != nil { return nil, err } if ads_v := r.FormValue("autods"); ads_v != "" { ads_i, err := strconv.Atoi(ads_v) if err != nil { return nil, err } if err := oreq.AutoDownsample(ads_i); err != nil { return nil, err } } ar := make(map[int]bool) for _, v := range r.Form["autorate"] { if i, err := strconv.Atoi(v); err == nil { ar[i] = true } } queries := make([]string, len(oreq.Queries)) var start, end string var startT, endT time.Time if s, ok := oreq.Start.(string); ok && strings.Contains(s, "-ago") { startT, err = opentsdb.ParseTime(s) if err != nil { return nil, err } start = strings.TrimSuffix(s, "-ago") } if s, ok := oreq.End.(string); ok && strings.Contains(s, "-ago") { endT, err = opentsdb.ParseTime(s) if err != nil { return nil, err } end = strings.TrimSuffix(s, "-ago") } if start == "" && end == "" { s, sok := oreq.Start.(int64) e, eok := oreq.End.(int64) if sok && eok { start = fmt.Sprintf("%vs", e-s) startT = time.Unix(s, 0) endT = time.Unix(e, 0) if err != nil { return nil, err } } } if endT.Equal(time.Time{}) { endT = time.Now().UTC() } m_units := make(map[string]string) for i, q := range oreq.Queries { if ar[i] { meta, err := schedule.MetadataMetrics(q.Metric) if err != nil { return nil, err } if meta == nil { return nil, fmt.Errorf("no metadata for %s: cannot use auto rate", q) } if meta.Unit != "" { m_units[q.Metric] = meta.Unit } if meta.Rate != "" { switch meta.Rate { case metadata.Gauge: // ignore case metadata.Rate: q.Rate = true case metadata.Counter: q.Rate = true q.RateOptions = opentsdb.RateOptions{ Counter: true, ResetValue: 1, } default: return nil, fmt.Errorf("unknown metadata rate: %s", meta.Rate) } } } queries[i] = fmt.Sprintf(`q("%v", "%v", "%v")`, q, start, end) if !schedule.SystemConf.GetTSDBContext().Version().FilterSupport() { if err := schedule.Search.Expand(q); err != nil { return nil, err } } } var tr opentsdb.ResponseSet b, _ := json.MarshalIndent(oreq, "", " ") t.StepCustomTiming("tsdb", "query", string(b), func() { h := schedule.SystemConf.GetTSDBHost() if h == "" { err = fmt.Errorf("tsdbHost not set") return } tr, err = oreq.Query(h) }) if err != nil { return nil, err } cs, err := makeChart(tr, m_units) if err != nil { return nil, err } if _, present := r.Form["png"]; present { c := chart.ScatterChart{ Title: fmt.Sprintf("%v - %v", oreq.Start, queries), } c.XRange.Time = true if min, err := strconv.ParseFloat(r.FormValue("min"), 64); err == nil { c.YRange.MinMode.Fixed = true c.YRange.MinMode.Value = min } if max, err := strconv.ParseFloat(r.FormValue("max"), 64); err == nil { c.YRange.MaxMode.Fixed = true c.YRange.MaxMode.Value = max } for ri, r := range cs { pts := make([]chart.EPoint, len(r.Data)) for idx, v := range r.Data { pts[idx].X = v[0] pts[idx].Y = v[1] } slice.Sort(pts, func(i, j int) bool { return pts[i].X < pts[j].X }) c.AddData(r.Name, pts, chart.PlotStyleLinesPoints, sched.Autostyle(ri)) } w.Header().Set("Content-Type", "image/svg+xml") white := color.RGBA{0xff, 0xff, 0xff, 0xff} const width = 800 const height = 600 s := svg.New(w) s.Start(width, height) s.Rect(0, 0, width, height, "fill: #ffffff") sgr := svgg.AddTo(s, 0, 0, width, height, "", 12, white) c.Plot(sgr) s.End() return nil, nil } var a []annotate.Annotation warnings := []string{} if schedule.SystemConf.AnnotateEnabled() { a, err = annotateBackend.GetAnnotations(&startT, &endT) if err != nil { warnings = append(warnings, fmt.Sprintf("unable to get annotations: %v", err)) } } return struct { Queries []string Series []*chartSeries Annotations []annotate.Annotation Warnings []string }{ queries, cs, a, warnings, }, nil }
func reverse(service Servicer, all bool) error { initialized, err := service.Initialized() if err != nil { return fmt.Errorf("unable to check for database state: %s", err) } if !initialized { return fmt.Errorf("uninitialized database") } available, err := service.Available() if err != nil { return fmt.Errorf("unable to retrieve available migrations: %s", err) } applied, err := service.Applied() if err != nil { return fmt.Errorf("unable to retrieve applied migrations: %s", err) } if len(applied) == 0 { return nil } var i, j = len(available) - 1, len(applied) - 1 for i >= 0 && j >= 0 && available[i].Name > applied[j].Name { i-- } for i >= 0 && j >= 0 { if available[i].Name == applied[j].Name { i-- j-- continue } if available[i].Name < applied[j].Name { return fmt.Errorf("missing migration: %s", applied[j].Name) } if available[i].Name > applied[j].Name { return fmt.Errorf("out of order migration: %s", available[i].Name) } } if i >= 0 { return fmt.Errorf("out of order migration: %s", available[i].Name) } if j >= 0 { return fmt.Errorf("missing migration: %s", applied[j].Name) } slice.Sort(applied, func(i, j int) bool { return applied[i].Name > applied[j].Name }) for _, migration := range applied { err := service.Reverse(migration) if err != nil { return err } if !all { return nil } } return nil }
func (s *Schedule) MarshalGroups(T miniprofiler.Timer, filter string) (*StateGroups, error) { var silenced SilenceTester T.Step("Silenced", func(miniprofiler.Timer) { silenced = s.Silenced() }) var groups map[StateTuple]States var err error status := make(States) t := StateGroups{ TimeAndDate: s.SystemConf.GetTimeAndDate(), } t.FailingAlerts, t.UnclosedErrors = s.getErrorCounts() T.Step("Setup", func(miniprofiler.Timer) { status2, err2 := s.GetOpenStates() if err2 != nil { err = err2 return } var parsedExpr *boolq.Tree parsedExpr, err2 = boolq.Parse(filter) if err2 != nil { err = err2 return } for k, v := range status2 { a := s.RuleConf.GetAlert(k.Name()) if a == nil { slog.Errorf("unknown alert %s. Force closing.", k.Name()) if err2 = s.ActionByAlertKey("bosun", "closing because alert doesn't exist.", models.ActionForceClose, k); err2 != nil { slog.Error(err2) } continue } is, err2 := MakeIncidentSummary(s.RuleConf, silenced, v) if err2 != nil { err = err2 return } match := false match, err2 = boolq.AskParsedExpr(parsedExpr, is) if err2 != nil { err = err2 return } if match { status[k] = v } } }) if err != nil { return nil, err } T.Step("GroupStates", func(T miniprofiler.Timer) { groups = status.GroupStates(silenced) }) T.Step("groups", func(T miniprofiler.Timer) { for tuple, states := range groups { var grouped []*StateGroup switch tuple.Status { case models.StWarning, models.StCritical, models.StUnknown: var sets map[string]models.AlertKeys T.Step(fmt.Sprintf("GroupSets (%d): %v", len(states), tuple), func(T miniprofiler.Timer) { sets = states.GroupSets(s.SystemConf.GetMinGroupSize()) }) for name, group := range sets { g := StateGroup{ Active: tuple.Active, Status: tuple.Status, CurrentStatus: tuple.CurrentStatus, Silenced: tuple.Silenced, Subject: fmt.Sprintf("%s - %s", tuple.Status, name), } for _, ak := range group { st := status[ak] st.Body = "" st.EmailBody = nil st.Attachments = nil g.Children = append(g.Children, &StateGroup{ Active: tuple.Active, Status: tuple.Status, Silenced: tuple.Silenced, AlertKey: ak, Alert: ak.Name(), Subject: string(st.Subject), Ago: marshalTime(st.Last().Time), State: st, IsError: !s.AlertSuccessful(ak.Name()), }) } if len(g.Children) == 1 && g.Children[0].Subject != "" { g.Subject = g.Children[0].Subject } grouped = append(grouped, &g) } default: continue } if tuple.NeedAck { t.Groups.NeedAck = append(t.Groups.NeedAck, grouped...) } else { t.Groups.Acknowledged = append(t.Groups.Acknowledged, grouped...) } } }) T.Step("sort", func(T miniprofiler.Timer) { gsort := func(grp []*StateGroup) func(i, j int) bool { return func(i, j int) bool { a := grp[i] b := grp[j] if a.Active && !b.Active { return true } else if !a.Active && b.Active { return false } if a.Status != b.Status { return a.Status > b.Status } if a.AlertKey != b.AlertKey { return a.AlertKey < b.AlertKey } return a.Subject < b.Subject } } slice.Sort(t.Groups.NeedAck, gsort(t.Groups.NeedAck)) slice.Sort(t.Groups.Acknowledged, gsort(t.Groups.Acknowledged)) }) return &t, nil }
func (srv *Server) commands() { srv.state = stateStop var next, stop, tick, play, pause, prev func() var timer <-chan time.Time waiters := make(map[*websocket.Conn]chan struct{}) broadcastData := func(wd *waitData) { for ws := range waiters { go func(ws *websocket.Conn) { if err := websocket.JSON.Send(ws, wd); err != nil { srv.ch <- cmdDeleteWS(ws) } }(ws) } } broadcast := func(wt waitType) { wd := srv.makeWaitData(wt) broadcastData(wd) } broadcastErr := func(err error) { printErr(err) v := struct { Time time.Time Error string }{ time.Now().UTC(), err.Error(), } broadcastData(&waitData{ Type: waitError, Data: v, }) } newWS := func(c cmdNewWS) { ws := (*websocket.Conn)(c.ws) waiters[ws] = c.done inits := []waitType{ waitPlaylist, waitProtocols, waitStatus, waitTracks, } for _, wt := range inits { data := srv.makeWaitData(wt) go func() { if err := websocket.JSON.Send(ws, data); err != nil { srv.ch <- cmdDeleteWS(ws) return } }() } } deleteWS := func(c cmdDeleteWS) { ws := (*websocket.Conn)(c) ch := waiters[ws] if ch == nil { return } close(ch) delete(waiters, ws) } prev = func() { log.Println("prev") srv.PlaylistIndex-- if srv.elapsed < time.Second*3 { srv.PlaylistIndex-- } if srv.PlaylistIndex < 0 { srv.PlaylistIndex = 0 } next() } pause = func() { log.Println("pause") switch srv.state { case statePause, stateStop: log.Println("pause: resume") srv.audioch <- audioPlay{} srv.state = statePlay case statePlay: log.Println("pause: pause") srv.audioch <- audioStop{} srv.state = statePause } } next = func() { log.Println("next") stop() play() } var forceNext = false stop = func() { log.Println("stop") srv.state = stateStop srv.audioch <- audioStop{} if srv.song != nil || forceNext { if srv.Random && len(srv.Queue) > 1 { n := srv.PlaylistIndex for n == srv.PlaylistIndex { n = rand.Intn(len(srv.Queue)) } srv.PlaylistIndex = n } else { srv.PlaylistIndex++ } } forceNext = false srv.song = nil srv.elapsed = 0 } var inst protocol.Instance var sid SongID sendNext := func() { go func() { srv.ch <- cmdNext }() } nextOpen := time.After(0) tick = func() { const expected = 4096 if false && srv.elapsed > srv.info.Time { log.Println("elapsed time completed", srv.elapsed, srv.info.Time) stop() } if srv.song == nil { <-nextOpen nextOpen = time.After(time.Second / 2) defer broadcast(waitStatus) if len(srv.Queue) == 0 { log.Println("empty queue") stop() return } if srv.PlaylistIndex >= len(srv.Queue) { if srv.Repeat { srv.PlaylistIndex = 0 } else { log.Println("end of queue", srv.PlaylistIndex, len(srv.Queue)) stop() return } } srv.songID = srv.Queue[srv.PlaylistIndex] sid = srv.songID if info, err := srv.getSong(sid); err != nil { broadcastErr(err) forceNext = true sendNext() return } else { srv.info = *info } inst = srv.Protocols[sid.Protocol()][sid.Key()] song, err := inst.GetSong(sid.ID()) if err != nil { forceNext = true broadcastErr(err) sendNext() return } srv.song = song sr, ch, err := srv.song.Init() if err != nil { srv.song.Close() srv.song = nil broadcastErr(err) sendNext() return } params := audioSetParams{ sr: sr, ch: ch, dur: srv.info.Time, play: srv.song.Play, err: make(chan error), } srv.audioch <- params if err := <-params.err; err != nil { broadcastErr(err) sendNext() return } srv.elapsed = 0 log.Println("playing", srv.info.Title, sr, ch) srv.state = statePlay } } infoTimer := func() { timer = time.After(time.Second) if inst == nil { return } // Check for updated song info. if info, err := inst.Info(sid.ID()); err != nil { broadcastErr(err) } else if srv.info != *info { srv.info = *info broadcast(waitStatus) } } restart := func() { log.Println("attempting to restart song") n := srv.PlaylistIndex stop() srv.PlaylistIndex = n play() } play = func() { log.Println("play") if srv.PlaylistIndex > len(srv.Queue) { srv.PlaylistIndex = 0 } tick() } playIdx := func(c cmdPlayIdx) { stop() srv.PlaylistIndex = int(c) play() } playTrack := func(c cmdPlayTrack) { t := SongID(c) info, err := srv.getSong(t) if err != nil { broadcastErr(err) return } album := info.Album p, err := srv.getInstance(t.Protocol(), t.Key()) if err != nil { broadcastErr(err) return } list, err := p.List() if err != nil { broadcastErr(err) return } top := codec.NewID(t.Protocol(), t.Key()) var ids []codec.ID for id, si := range list { if si.Album == album { ids = append(ids, id) } } slice.Sort(ids, func(i, j int) bool { a := list[ids[i]] b := list[ids[j]] return a.Track < b.Track }) plc := PlaylistChange{[]string{"clear"}} for _, v := range ids { plc = append(plc, []string{"add", string(top.Push(string(v)))}) } n, _, err := srv.playlistChange(srv.Queue, plc) if err != nil { broadcastErr(err) return } stop() srv.Queue = n srv.PlaylistIndex = 0 for i, s := range srv.Queue { if s == t { srv.PlaylistIndex = i } } play() broadcast(waitPlaylist) } removeDeleted := func() { for n, p := range srv.Playlists { p = srv.removeDeleted(p) if len(p) == 0 { delete(srv.Playlists, n) } else { srv.Playlists[n] = p } } srv.Queue = srv.removeDeleted(srv.Queue) if info, _ := srv.getSong(srv.songID); info == nil { playing := srv.state == statePlay stop() if playing { srv.PlaylistIndex = 0 play() } } broadcast(waitPlaylist) } protocolRemove := func(c cmdProtocolRemove) { prots, ok := srv.Protocols[c.protocol] if !ok { return } delete(prots, c.key) if srv.Token != "" { d := models.Delete{ Protocol: c.protocol, Name: c.key, } go func() { r, err := srv.request("/api/source/delete", &d) if err != nil { srv.ch <- cmdError(err) return } r.Close() }() } broadcast(waitTracks) broadcast(waitProtocols) } removeInProgress := func(c cmdRemoveInProgress) { delete(srv.inprogress, codec.ID(c)) broadcast(waitProtocols) } protocolAdd := func(c cmdProtocolAdd) { name, key := c.Name, c.Instance.Key() id := codec.NewID(name, key) if srv.inprogress[id] { broadcastErr(fmt.Errorf("already adding %s: %s", name, key)) return } if _, err := srv.getInstance(name, key); err == nil { broadcastErr(fmt.Errorf("already have %s: %s", name, key)) return } srv.inprogress[id] = true broadcast(waitProtocols) go func() { defer func() { srv.ch <- cmdRemoveInProgress(id) }() songs, err := c.Instance.Refresh() if err != nil { srv.ch <- cmdError(err) return } for k, v := range songs { if v.Time > 0 && v.Time < srv.MinDuration { delete(songs, k) } } srv.ch <- cmdProtocolAddInstance(c) }() } protocolAddInstance := func(c cmdProtocolAddInstance) { srv.Protocols[c.Name][c.Instance.Key()] = c.Instance if srv.Token != "" { srv.ch <- cmdPutSource{ protocol: c.Name, key: c.Instance.Key(), } } broadcast(waitTracks) broadcast(waitProtocols) } queueChange := func(c cmdQueueChange) { n, clear, err := srv.playlistChange(srv.Queue, PlaylistChange(c)) if err != nil { broadcastErr(err) return } srv.Queue = n if clear || len(n) == 0 { stop() srv.PlaylistIndex = 0 } broadcast(waitPlaylist) } playlistChange := func(c cmdPlaylistChange) { p := srv.Playlists[c.name] n, _, err := srv.playlistChange(p, c.plc) if err != nil { broadcastErr(err) return } if len(n) == 0 { delete(srv.Playlists, c.name) } else { srv.Playlists[c.name] = n } broadcast(waitPlaylist) } queueSave := func() { if srv.savePending { return } srv.savePending = true time.AfterFunc(time.Second, func() { srv.ch <- cmdDoSave{} }) } doSave := func() { if err := srv.save(); err != nil { broadcastErr(err) } } addOAuth := func(c cmdAddOAuth) { go func() { prot, err := protocol.ByName(c.name) if err != nil { c.done <- err return } t, err := prot.OAuth.Exchange(oauth2.NoContext, c.r.FormValue("code")) if err != nil { c.done <- err return } // "Bearer" was added for dropbox. It happens to work also with Google Music's // OAuth. This may need to be changed to be protocol-specific in the future. t.TokenType = "Bearer" instance, err := prot.NewInstance(nil, t) if err != nil { c.done <- err return } srv.ch <- cmdProtocolAdd{ Name: c.name, Instance: instance, } c.done <- nil }() } setMinDuration := func(c cmdMinDuration) { srv.MinDuration = time.Duration(c) } doSeek := func(c cmdSeek) { if time.Duration(c) > srv.info.Time { return } srv.audioch <- c } setUsername := func(c cmdSetUsername) { srv.Username = string(c) } makeSource := func(protocol, key string) ([]*models.Source, error) { // name and key may be empty to match all var ss []*models.Source for prot, m := range srv.Protocols { if prot != protocol && protocol != "" { continue } for name, p := range m { if name != key && key != "" { continue } buf := new(bytes.Buffer) gw := gzip.NewWriter(buf) if err := gob.NewEncoder(gw).Encode(p); err != nil { return nil, err } if err := gw.Close(); err != nil { return nil, err } ss = append(ss, &models.Source{ Protocol: prot, Name: name, Blob: buf.Bytes(), }) } } return ss, nil } sendSource := func(ss []*models.Source) error { r, err := srv.request("/api/source/set", &ss) if err != nil { return err } r.Close() return nil } putSource := func(c cmdPutSource) { ss, err := makeSource(c.protocol, c.key) if err != nil { broadcastErr(fmt.Errorf("could not set sources: %v", err)) return } if err := sendSource(ss); err != nil { broadcastErr(fmt.Errorf("could not set sources: %v", err)) } } tokenRegister := func(c cmdTokenRegister) { srv.Token = "" if c != "" { srv.Token = string(c) ss, err := makeSource("", "") if err != nil { broadcastErr(err) return } go func() { if err := sendSource(ss); err != nil { srv.ch <- cmdError(err) return } r, err := srv.request("/api/source/get", nil) if err != nil { srv.ch <- cmdError(fmt.Errorf("could not get sources: %v", err)) return } defer r.Close() if err := json.NewDecoder(r).Decode(&ss); err != nil { srv.ch <- cmdError(err) return } srv.ch <- cmdSetSources(ss) }() } go func() { srv.ch <- cmdSetUsername("") if c == "" { return } r, err := srv.request("/api/username", nil) if err != nil { srv.ch <- cmdError(err) return } defer r.Close() var u cmdSetUsername if err := json.NewDecoder(r).Decode(&u); err != nil { srv.ch <- cmdError(err) return } srv.ch <- u }() } setSources := func(c cmdSetSources) { ps := protocol.Map() for _, s := range c { proto, err := protocol.ByName(s.Protocol) if err != nil { broadcastErr(err) return } if _, ok := ps[s.Protocol]; !ok { ps[s.Protocol] = make(map[string]protocol.Instance) } r, err := gzip.NewReader(bytes.NewReader(s.Blob)) if err != nil { broadcastErr(err) return } defer r.Close() p, err := proto.Decode(r) if err != nil { broadcastErr(err) return } ps[s.Protocol][s.Name] = p } srv.Protocols = ps go func() { // protocolRefresh uses srv.Protocols, so for i, s := range c { last := i == len(c)-1 srv.ch <- cmdProtocolRefresh{ protocol: s.Protocol, key: s.Name, list: true, doDelete: last, err: make(chan error, 1), } } }() } sendWaitData := func(c cmdWaitData) { c.done <- srv.makeWaitData(c.wt) } isRefreshing := make(map[codec.ID]bool) protocolRefresh := func(c cmdProtocolRefresh) { id := codec.NewID(c.protocol, c.key) if isRefreshing[id] { c.err <- nil return } inst, err := srv.getInstance(c.protocol, c.key) if err != nil { c.err <- err return } isRefreshing[id] = true go func() { defer func() { delete(isRefreshing, id) }() f := inst.Refresh if c.list { f = inst.List } songs, err := f() if err != nil { c.err <- err return } for k, v := range songs { if v.Time > 0 && v.Time < srv.MinDuration { delete(songs, k) } } if c.doDelete { srv.ch <- cmdRemoveDeleted{} } if srv.Token != "" { srv.ch <- cmdPutSource{ protocol: c.protocol, key: c.key, } } c.err <- nil }() } ch := make(chan interface{}) go func() { for c := range srv.ch { go func(c interface{}) { timer := time.AfterFunc(time.Second*10, func() { log.Printf("%T: %#v\n", c, c) panic("delay timer expired") }) ch <- c timer.Stop() }(c) } }() infoTimer() for { select { case <-timer: infoTimer() case c := <-ch: if c, ok := c.(cmdSetTime); ok { d := time.Duration(c) change := srv.elapsed - d if change < 0 { change = -change } srv.elapsed = d if change > time.Second { broadcast(waitStatus) } continue } save := true log.Printf("%T\n", c) switch c := c.(type) { case controlCmd: switch c { case cmdPlay: save = false play() case cmdStop: save = false stop() case cmdNext: next() case cmdPause: save = false pause() case cmdPrev: prev() case cmdRandom: srv.Random = !srv.Random case cmdRepeat: srv.Repeat = !srv.Repeat case cmdRestartSong: restart() default: panic(c) } case cmdPlayIdx: playIdx(c) case cmdPlayTrack: playTrack(c) case cmdProtocolRemove: protocolRemove(c) case cmdQueueChange: queueChange(c) case cmdPlaylistChange: playlistChange(c) case cmdNewWS: save = false newWS(c) case cmdDeleteWS: save = false deleteWS(c) case cmdDoSave: save = false doSave() case cmdAddOAuth: addOAuth(c) case cmdSeek: doSeek(c) save = false case cmdMinDuration: setMinDuration(c) case cmdTokenRegister: tokenRegister(c) case cmdSetUsername: setUsername(c) case cmdSetSources: setSources(c) case cmdProtocolAdd: protocolAdd(c) case cmdProtocolAddInstance: protocolAddInstance(c) case cmdRemoveDeleted: removeDeleted() case cmdRemoveInProgress: removeInProgress(c) case cmdError: broadcastErr(error(c)) save = false case cmdWaitData: sendWaitData(c) save = false case cmdPutSource: putSource(c) save = false case cmdProtocolRefresh: protocolRefresh(c) default: panic(c) } broadcast(waitStatus) if save { queueSave() } } } }
// Print the character sheet on the screen func (c *Character) Print() { // Print the name fmt.Printf("%s\t%s\n", theme.Title("Name"), c.Name) // Print the backgrounds backgrounds := []Background{} for _, background := range c.Backgrounds { backgrounds = append(backgrounds, background) } slice.Sort(backgrounds, func(i, j int) bool { if backgrounds[i].Type != backgrounds[j].Type { return backgrounds[i].Type < backgrounds[j].Type } return backgrounds[i].Name < backgrounds[j].Name }) for _, background := range backgrounds { fmt.Printf("%s\t%s\n", theme.Title(strings.Title(background.Type)), strings.Title(background.Name)) } // Print the aptitudes aptitudes := []Aptitude{} for _, aptitude := range c.Aptitudes { aptitudes = append(aptitudes, aptitude) } slice.Sort(aptitudes, func(i, j int) bool { return aptitudes[i] < aptitudes[j] }) fmt.Printf("\n%s (%s)\n", theme.Title("Aptitudes"), theme.Value(fmt.Sprintf("%d", len(aptitudes)))) for _, aptitude := range aptitudes { fmt.Printf("%s\n", strings.Title(string(aptitude))) } // Print the experience fmt.Printf("\n%s\t%d/%d\n", theme.Title("Experience"), c.Spent, c.Experience) // Print the characteristics var characteristicSum int characteristics := []Characteristic{} for _, characteristic := range c.Characteristics { characteristicSum += characteristic.Value characteristics = append(characteristics, characteristic) } slice.Sort(characteristics, func(i, j int) bool { return characteristics[i].Name < characteristics[j].Name }) fmt.Printf("\n%s (%s)\n", theme.Title("Characteristics"), theme.Value(fmt.Sprintf("%d", characteristicSum))) for _, characteristic := range characteristics { fmt.Printf("%s\t%s %s\n", characteristic.Name, theme.Value(characteristic.Value), theme.Value(characteristic.Level())) } // Print the gauges if len(c.Gauges) != 0 { fmt.Printf("\n%s\n", theme.Title("Gauges")) gauges := []Gauge{} for _, gauge := range c.Gauges { gauges = append(gauges, gauge) } slice.Sort(gauges, func(i, j int) bool { return gauges[i].Name < gauges[j].Name }) for _, gauge := range gauges { fmt.Printf("%s\t%s\n", gauge.Name, theme.Value(gauge.Value)) } } // Print the skills if len(c.Skills) != 0 { // Print the skills using a tabwriter fmt.Printf("\n%s\n", theme.Title("Skills")) skills := []Skill{} for _, skill := range c.Skills { skills = append(skills, skill) } slice.Sort(skills, func(i, j int) bool { return skills[i].FullName() < skills[j].FullName() }) w := tabwriter.NewWriter(os.Stdout, 10, 1, 2, ' ', 0) for _, skill := range skills { fmt.Fprintf(w, "%s\t+%s\n", strings.Title(skill.FullName()), theme.Value((skill.Tier-1)*10)) } w.Flush() } // Print the talents if len(c.Talents) != 0 { fmt.Printf("\n%s\n", theme.Title("Talents")) talents := []Talent{} for _, talent := range c.Talents { talents = append(talents, talent) } slice.Sort(talents, func(i, j int) bool { return talents[i].FullName() < talents[j].FullName() }) w := tabwriter.NewWriter(os.Stdout, 10, 1, 2, ' ', 0) for _, talent := range talents { if talent.Value != 1 { fmt.Fprintf(w, "%s (%d)\t%s\n", strings.Title(talent.FullName()), talent.Value, talent.Description) } else { fmt.Fprintf(w, "%s\t%s\n", strings.Title(talent.FullName()), talent.Description) } } w.Flush() } // Print the spells if len(c.Spells) != 0 { fmt.Printf("\n%s\n", theme.Title("Spells")) spells := []Spell{} for _, spell := range c.Spells { spells = append(spells, spell) } slice.Sort(spells, func(i, j int) bool { return spells[i].Name < spells[j].Name }) w := tabwriter.NewWriter(os.Stdout, 10, 1, 2, ' ', 0) for _, spell := range spells { fmt.Fprintf(w, "%s\t%s\n", strings.Title(spell.Name), spell.Description) } w.Flush() } // Print the special rules if len(c.Rules) != 0 { fmt.Printf("\n%s\n", theme.Title("Rules")) rules := []Rule{} for _, rule := range c.Rules { rules = append(rules, rule) } slice.Sort(rules, func(i, j int) bool { return rules[i].Name < rules[j].Name }) w := tabwriter.NewWriter(os.Stdout, 10, 1, 2, ' ', 0) for _, rule := range rules { fmt.Printf("%s\t%s\n", strings.Title(rule.Name), rule.Description) } w.Flush() } }
func Rule(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) { var from, to time.Time var err error if f := r.FormValue("from"); len(f) > 0 { from, err = time.Parse(tsdbFormatSecs, f) if err != nil { return nil, err } } if f := r.FormValue("to"); len(f) > 0 { to, err = time.Parse(tsdbFormatSecs, f) if err != nil { return nil, err } } intervals := 1 if i := r.FormValue("intervals"); len(i) > 0 { intervals, err = strconv.Atoi(r.FormValue("intervals")) if err != nil { return nil, err } if intervals < 1 { return nil, fmt.Errorf("must be > 0 intervals") } } if fz, tz := from.IsZero(), to.IsZero(); fz && tz { from = time.Now() } else if fz && !tz { return nil, fmt.Errorf("cannot specify to without from") } else if !fz && tz && intervals > 1 { return nil, fmt.Errorf("cannot specify intervals without from and to") } c, a, hash, err := buildConfig(r) if err != nil { return nil, err } ch := make(chan int) errch := make(chan error, intervals) resch := make(chan *ruleResult, intervals) var wg sync.WaitGroup diff := -from.Sub(to) if intervals > 1 { diff /= time.Duration(intervals - 1) } worker := func() { wg.Add(1) for interval := range ch { t.Step(fmt.Sprintf("interval %v", interval), func(t miniprofiler.Timer) { now := from.Add(diff * time.Duration(interval)) res, err := procRule(t, c, a, now, interval != 0, r.FormValue("email"), r.FormValue("template_group")) resch <- res errch <- err }) } defer wg.Done() } for i := 0; i < 20; i++ { go worker() } for i := 0; i < intervals; i++ { ch <- i } close(ch) wg.Wait() close(errch) close(resch) type Result struct { Group models.AlertKey Result *models.Event } type Set struct { Critical, Warning, Normal int Time string Results []*Result `json:",omitempty"` } type History struct { Time, EndTime time.Time Status string } type Histories struct { History []*History } ret := struct { Errors []string `json:",omitempty"` Warnings []string `json:",omitempty"` Sets []*Set AlertHistory map[models.AlertKey]*Histories Body string `json:",omitempty"` Subject string `json:",omitempty"` Data interface{} `json:",omitempty"` Hash string }{ AlertHistory: make(map[models.AlertKey]*Histories), Hash: hash, } for err := range errch { if err == nil { continue } ret.Errors = append(ret.Errors, err.Error()) } for res := range resch { if res == nil { continue } set := Set{ Critical: len(res.Criticals), Warning: len(res.Warnings), Normal: len(res.Normals), Time: res.Time.Format(tsdbFormatSecs), } if res.Data != nil { ret.Body = res.Body ret.Subject = res.Subject ret.Data = res.Data for k, v := range res.Result { set.Results = append(set.Results, &Result{ Group: k, Result: v, }) } slice.Sort(set.Results, func(i, j int) bool { a := set.Results[i] b := set.Results[j] if a.Result.Status != b.Result.Status { return a.Result.Status > b.Result.Status } return a.Group < b.Group }) } for k, v := range res.Result { if ret.AlertHistory[k] == nil { ret.AlertHistory[k] = new(Histories) } h := ret.AlertHistory[k] h.History = append(h.History, &History{ Time: v.Time, Status: v.Status.String(), }) } ret.Sets = append(ret.Sets, &set) ret.Warnings = append(ret.Warnings, res.Warning...) } slice.Sort(ret.Sets, func(i, j int) bool { return ret.Sets[i].Time < ret.Sets[j].Time }) for _, histories := range ret.AlertHistory { hist := histories.History slice.Sort(hist, func(i, j int) bool { return hist[i].Time.Before(hist[j].Time) }) for i := 1; i < len(hist); i++ { if i < len(hist)-1 && hist[i].Status == hist[i-1].Status { hist = append(hist[:i], hist[i+1:]...) i-- } } for i, h := range hist[:len(hist)-1] { h.EndTime = hist[i+1].Time } histories.History = hist[:len(hist)-1] } return &ret, nil }
// Suggest the next purchasable upgrades of the character. func (c *Character) Suggest(universe Universe, max int, all bool, allowSpells bool) { // Aggregate each coster into a unique slice of costers. costers := []Coster{} for _, upgrade := range universe.Characteristics { costers = append(costers, upgrade) } for _, upgrade := range universe.Skills { costers = append(costers, upgrade) } for _, upgrade := range universe.Talents { costers = append(costers, upgrade) } for _, upgrade := range universe.Gauges { upgrade.Value = 1 costers = append(costers, upgrade) } if allowSpells { for _, upgrade := range universe.Spells { costers = append(costers, upgrade) } } // Default max value equals to the remaining XP. if max == 0 { max = c.Experience - c.Spent } // The slice of appliable upgrades. var appliable []Upgrade // Attempt to apply each coster once. for _, coster := range costers { var upgrade Upgrade // Don't propose the upgrade its cost cannot be defined cost, err := coster.Cost(universe, *c) if err != nil { continue } // Don't propose the upgrade if it is free. if cost == 0 { continue } // Don't propose the upgrade if it is too expensive. if !all && max < cost { continue } upgrade.Cost = &cost upgrade.Mark = MarkApply upgrade.Name = coster.DefaultName() err = coster.Apply(c, upgrade) if err != nil { continue } appliable = append(appliable, upgrade) } // Sort by cost then name. slice.Sort(appliable, func(i, j int) bool { ci, cj := *appliable[i].Cost, *appliable[j].Cost if ci == cj { return appliable[i].Name < appliable[j].Name } return ci < cj }) // Print the name. fmt.Printf("%s\t%s\n", theme.Title("Name"), c.Name) // Print the experience fmt.Printf("\n%s\t%d/%d\n", theme.Title("Experience"), c.Spent, c.Experience) // Print the history. fmt.Printf("\n%s\n", theme.Title("Suggestions")) w := tabwriter.NewWriter(os.Stdout, 10, 1, 2, ' ', 0) for i, upgrade := range appliable { if i > 0 && *appliable[i-1].Cost != *upgrade.Cost { fmt.Fprintln(w) } fmt.Fprintf(w, "%s\t%s\n", theme.Value(*upgrade.Cost), strings.Title(upgrade.Name)) } w.Flush() }