github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/core/datamodel/sort.go (about) 1 package datamodel 2 3 import ( 4 "sort" 5 6 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 7 ) 8 9 // Tri multicritère 10 11 type Critere struct { 12 Field rd.Field 13 Reverse bool 14 } 15 16 type CriteresTri struct { 17 skipDeterminisme bool 18 Fields []Critere 19 } 20 21 const maxCriteres = 5 22 23 // AddCritere renvoie la valeur mise à jour 24 func (c CriteresTri) AddCritere(field rd.Field, reverse bool) CriteresTri { 25 if len(c.Fields) > 0 && c.Fields[0].Field == field { 26 // on n'ajoute pas le même champ, on met juste à jour l'ordre de tri 27 c.Fields[0].Reverse = reverse 28 return c 29 } 30 out := append([]Critere{{Field: field, Reverse: reverse}}, c.Fields...) 31 if len(out) > maxCriteres { 32 out = out[:maxCriteres] 33 } 34 return CriteresTri{Fields: out, skipDeterminisme: c.skipDeterminisme} 35 } 36 37 func (c CriteresTri) compare(itemi, itemj rd.Item) bool { 38 // si reverse vaut true on renvoie le contraire de b 39 // si reverse faut false on renvoie b 40 41 for _, field := range c.Fields { 42 vi := itemi.Fields.Data(field.Field).Sortable() 43 vj := itemj.Fields.Data(field.Field).Sortable() 44 if vi == vj { // on teste le critère suivant 45 continue 46 } 47 return field.Reverse != (vi < vj) // il n'y a plus égalité ici 48 } 49 if c.skipDeterminisme { 50 return false 51 } 52 return itemi.Id.Int64() < itemj.Id.Int64() // déterministe 53 } 54 55 // SortCriteresChilds modifie sur place `liste` 56 // Le premier critère de `field` est le plus important. 57 func SortCriteresChilds(liste []rd.ItemChilds, criteres CriteresTri) { 58 sort.Slice(liste, func(i, j int) bool { 59 return criteres.compare(liste[i].Item, liste[j].Item) 60 }) 61 } 62 63 // SortCriteres modifie sur place `liste` 64 // Le premier critère de `field` est le plus important. 65 func SortCriteres(liste []rd.Item, criteres CriteresTri) { 66 sort.Slice(liste, func(i, j int) bool { 67 return criteres.compare(liste[i], liste[j]) 68 }) 69 } 70 71 // SortBy sorts `t` in place, accordind to field. 72 func SortBy(t rd.Table, field rd.Field, rev bool) { 73 ct := CriteresTri{Fields: []Critere{{Field: field, Reverse: rev}}} 74 sort.Slice(t, func(i, j int) bool { 75 return ct.compare(t[i], t[j]) 76 }) 77 } 78 79 // SortStableBy sorts `t` in place. 80 func SortStableBy(t rd.Table, field rd.Field, rev bool) { 81 ct := CriteresTri{Fields: []Critere{{Field: field, Reverse: rev}}, skipDeterminisme: true} 82 sort.SliceStable(t, func(i, j int) bool { 83 return ct.compare(t[i], t[j]) 84 }) 85 } 86 87 // Sort modifie sur place `liste` 88 func Sort(liste rd.Table, headers []rd.Header, section int, reverse bool) { 89 field := headers[section].Field 90 SortBy(liste, field, reverse) 91 }