github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/appengine/backend/backend3.go (about) 1 package backend 2 3 import ( 4 sc "github.com/pbberlin/tools/dsu/distributed_unancestored" 5 "github.com/pbberlin/tools/net/http/htmlfrag" 6 "github.com/pbberlin/tools/net/http/loghttp" 7 "github.com/pbberlin/tools/net/http/tplx" 8 "google.golang.org/appengine" 9 10 // "github.com/davecgh/go-spew/spew" 11 "net/http" 12 "sort" 13 "strings" 14 15 "github.com/pbberlin/tools/util" 16 aelog "google.golang.org/appengine/log" 17 ) 18 19 /* 20 I would love to use slices of *interfaces*, 21 instead of fixed types 22 23 VB1 []interface{} <---- preferable 24 VB1 []b1 <---- restrictive 25 26 But it is complicated to reach 27 the pointers to the actual structs, 28 if the structs are wrapped behind an interface. 29 30 myB1 := &(myB0.VB1a[i1]) 31 myB1.Fieldname += "_BBBBB" // works 32 33 myB1, ok := myB0.VB1[i1].(b1) 34 if !ok ... 35 myB1.Fieldname += "_BBBBB" // not working 36 37 myB1 := &(myB0.VB1[i1].(b1)) // impossible - "cannot take the address ..." 38 myB1 := &(myB0.VB1[i1]).(*b1) // impossible 39 40 (myB0.VB1[i1].(b1)).Heading += "_AAAAA" // impossible - "can not assign ..." 41 42 43 This solution seems not applicable without writing accessor methods for each field: 44 https://groups.google.com/forum/#!topic/golang-nuts/bxbUdSYdTSI 45 46 47 These are possible solutions, both using reflection 48 http://stackoverflow.com/questions/6395076/in-golang-using-reflect-how-do-you-set-the-value-of-a-struct-field 49 http://stackoverflow.com/questions/21379466/golang-get-a-pointer-to-a-field-of-a-struct-trough-an-interface 50 51 I implemented the first solution in util.GetIntField(), 52 but it's not working with generic arguments. 53 54 The second solution is too much complication for me - 55 I fall back to explicit typing: 56 57 for i1, _ := range myB0.VB1 { 58 59 myB0.VB1a[i1].Heading += "_AAAAA" // works 60 61 myB1 := &(myB0.VB1a[i1]) 62 myB1.Heading += "_BBBBB" // works 63 64 myB2 := (&myB0).VB1a[i1] 65 myB2.Heading += "_CCCCC" // works NOT 66 67 myB3 := myB0.VB1a[i1] 68 myB3.Heading += "_DDDDD" // works NOT 69 70 } 71 72 */ 73 74 //var myB0 = b0{NumYSectors: 2} 75 var myB0 B0 = B0{NumYSectors: 2} 76 77 func backend3(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { 78 79 c := appengine.NewContext(r) 80 81 var nColsBlock = 4 82 if r.FormValue("nColsBlock") != "" { 83 nColsBlock = util.Stoi(r.FormValue("nColsBlock")) 84 } 85 var nColsViewport = 6 86 if r.FormValue("nColsViewport") != "" { 87 nColsViewport = util.Stoi(r.FormValue("nColsViewport")) 88 } 89 90 myB0.VB1 = X 91 myB0.NumB1 = len(myB0.VB1) 92 myB0.NumB2 = 0 93 myB0.NColsViewport = nColsViewport 94 95 // compute basic meta data 96 for i1, _ := range myB0.VB1 { 97 myB0.NumB2 += len(myB0.VB1[i1].VB2) 98 for i2, _ := range myB0.VB1[i1].VB2 { 99 // number of chars 100 ro := myB0.VB1[i1].VB2[i2] // read only 101 myB0.VB1[i1].VB2[i2].Size = len(ro.Linktext) + len(ro.Description) 102 myB0.VB1[i1].VB2[i2].EditorialIndex = i2 103 } 104 } 105 106 // compute NCols - NRows for the block 107 for i1, _ := range myB0.VB1 { 108 myB0.VB1[i1].NCols = nColsBlock 109 if myB0.VB1[i1].NColsEditorial > 0 { 110 myB0.VB1[i1].NCols = myB0.VB1[i1].NColsEditorial 111 } 112 if len(myB0.VB1[i1].VB2) < nColsBlock && len(myB0.VB1[i1].VB2) > 0 { 113 myB0.VB1[i1].NCols = len(myB0.VB1[i1].VB2) 114 } 115 myB0.VB1[i1].NRows = complementRowsOrCols(len(myB0.VB1[i1].VB2), myB0.VB1[i1].NCols) 116 myB0.VB1[i1].Discrepancy = myB0.VB1[i1].NCols*myB0.VB1[i1].NRows - len(myB0.VB1[i1].VB2) 117 118 myB0.MaxNCols = util.Max(myB0.MaxNCols, myB0.VB1[i1].NCols) 119 myB0.MaxNRows = util.Max(myB0.MaxNRows, myB0.VB1[i1].NRows) 120 } 121 122 // compute NCols - NRows - sizeup to MaxNRows 123 for i1, _ := range myB0.VB1 { 124 if myB0.VB1[i1].NRows < myB0.MaxNRows { 125 myB0.VB1[i1].NRows = myB0.MaxNRows 126 myB0.VB1[i1].NCols = complementRowsOrCols(len(myB0.VB1[i1].VB2), myB0.VB1[i1].NRows) 127 myB0.VB1[i1].Discrepancy = myB0.VB1[i1].NCols*myB0.VB1[i1].NRows - len(myB0.VB1[i1].VB2) 128 } 129 } 130 131 // is first or last 132 for i1, _ := range myB0.VB1 { 133 for i2, _ := range myB0.VB1[i1].VB2 { 134 myB0.VB1[i1].VB2[i2].IsFirst = false 135 myB0.VB1[i1].VB2[i2].IsLast = false 136 if i2%myB0.VB1[i1].NCols == 0 { 137 myB0.VB1[i1].VB2[i2].IsFirst = true 138 } 139 if i2%myB0.VB1[i1].NCols == (myB0.VB1[i1].NCols - 1) { 140 myB0.VB1[i1].VB2[i2].IsLast = true 141 } 142 //aelog.Infof(c,"first-last %v %v \n", i2, i2%myB0.VB1[i1].NCols) 143 } 144 } 145 146 // create slices with the data to be sorted 147 for i1, _ := range myB0.VB1 { 148 sh1 := make([]Order, len(myB0.VB1[i1].VB2)) 149 myB0.VB1[i1].BySize = ByInt(sh1) 150 sh2 := make([]Order, len(myB0.VB1[i1].VB2)) 151 myB0.VB1[i1].ByHeading = ByStr(sh2) 152 // fill in the data - to be sorted later 153 for i2, _ := range myB0.VB1[i1].VB2 { 154 ro := myB0.VB1[i1].VB2[i2] // read only 155 myB0.VB1[i1].BySize[i2].IdxSrc = i2 156 myB0.VB1[i1].BySize[i2].ByI = len(ro.Linktext) + len(ro.Description) 157 myB0.VB1[i1].ByHeading[i2].IdxSrc = i2 158 myB0.VB1[i1].ByHeading[i2].ByS = strings.ToLower(ro.Linktext) 159 } 160 } 161 162 // actual rearranging of the sorting date 163 for i1, _ := range myB0.VB1 { 164 sort.Sort(myB0.VB1[i1].BySize) 165 sort.Sort(myB0.VB1[i1].ByHeading) 166 aelog.Infof(c, "-- Sorting %v", myB0.VB1[i1].Heading) 167 // for i, v := range myB0.VB1[i1].BySize { 168 // aelog.Infof(c,"---- %v %v %v", i, v.IdxSrc, v.ByI) 169 // } 170 // for i, v := range myB0.VB1[i1].ByHeading { 171 // aelog.Infof(c,"---- %v %v %v", i, v.IdxSrc, v.ByS) 172 // } 173 } 174 175 path := m["dir"].(string) + m["base"].(string) 176 177 cntr, _ := sc.Count(c, path) 178 179 add, tplExec := tplx.FuncTplBuilder(w, r) 180 add("n_html_title", "Backend", nil) 181 182 add("n_cont_0", "<style>"+htmlfrag.CSSColumnsWidth(nColsViewport)+"</style>", "") 183 add("n_cont_1", tplx.PrefixLff+"backend3_body", myB0) 184 add("tpl_legend", tplx.PrefixLff+"backend3_body_embed01", "") 185 add("n_cont_2", "<p>{{.}} views</p>", cntr) 186 187 sDumped := "" 188 //sDumped = spew.Sdump(myB0) 189 add("n_cont_3", "<pre>{{.}} </pre>", sDumped) 190 191 tplExec(w, r) 192 193 } 194 195 func prepareLayout(l B0) { 196 197 } 198 199 func complementRowsOrCols(nBlocks int, nRowOrCol int) int { 200 if nRowOrCol < 1 { 201 panic("Count of Cols or Rows must be given") 202 } 203 nCompl := nBlocks / nRowOrCol 204 if nBlocks%nRowOrCol != 0 { 205 nCompl++ 206 } 207 return nCompl 208 209 } 210 211 func init() { 212 prepareLayout(myB0) 213 http.HandleFunc("/backend3", loghttp.Adapter(backend3)) 214 }