1

Refactoring

This commit is contained in:
Alex Yatskov 2015-03-24 20:04:52 +09:00
parent 5b158c27b2
commit 59accf2e53
3 changed files with 40 additions and 40 deletions

View File

@ -37,9 +37,9 @@ var db *sql.DB
func executeQuery(rw http.ResponseWriter, req *http.Request) { func executeQuery(rw http.ResponseWriter, req *http.Request) {
type Request struct { type Request struct {
features Features features featureMap
bounds Bounds bounds queryBounds
geo Geo geo geoContext
walkingDist float64 walkingDist float64
minScore float64 minScore float64
hintSteps int hintSteps int

View File

@ -22,59 +22,59 @@
package main package main
type Context struct { type queryContext struct {
geo Geo geo geoContext
latitude float64 latitude float64
longitude float64 longitude float64
profile Features profile featureMap
walkingDist float64 walkingDist float64
} }
type Projection struct { type queryProjection struct {
sample float64 sample float64
stats RecordStats stats recordStats
} }
type Features map[interface{}]float64 type featureMap map[interface{}]float64
type RecordStats struct { type recordStats struct {
compatibility float64 compatibility float64
count int count int
} }
type Bounds struct { type queryBounds struct {
max float64 max float64
min float64 min float64
} }
type Geo struct { type geoContext struct {
latitude float64 latitude float64
longitude float64 longitude float64
valid bool valid bool
} }
type Record struct { type record struct {
accessCount int accessCount int
compatibility float64 compatibility float64
distanceToStn float64 distanceToStn float64
distanceToUser float64 distanceToUser float64
features Features features featureMap
geo Geo geo geoContext
id int id int
name string name string
score float64 score float64
} }
type Records []Record type records []record
func (slice Records) Len() int { func (slice records) Len() int {
return len(slice) return len(slice)
} }
func (slice Records) Less(i, j int) bool { func (slice records) Less(i, j int) bool {
return slice[i].score > slice[j].score return slice[i].score > slice[j].score
} }
func (slice Records) Swap(i, j int) { func (slice records) Swap(i, j int) {
slice[i], slice[j] = slice[j], slice[i] slice[i], slice[j] = slice[j], slice[i]
} }

42
util.go
View File

@ -29,7 +29,7 @@ import (
"sort" "sort"
) )
func innerProduct(features1 Features, features2 Features) float64 { func innerProduct(features1 featureMap, features2 featureMap) float64 {
var result float64 var result float64
for key, value1 := range features1 { for key, value1 := range features1 {
value2, _ := features2[key] value2, _ := features2[key]
@ -39,17 +39,17 @@ func innerProduct(features1 Features, features2 Features) float64 {
return result return result
} }
func walkMatches(records Records, features Features, minScore float64, callback func(Record, float64)) { func walkMatches(entries records, features featureMap, minScore float64, callback func(record, float64)) {
for _, record := range records { for _, record := range entries {
if score := innerProduct(features, record.features); score >= minScore { if score := innerProduct(features, record.features); score >= minScore {
callback(record, score) callback(record, score)
} }
} }
} }
func statRecords(records Records, features Features, minScore float64) RecordStats { func statRecords(entries records, features featureMap, minScore float64) recordStats {
var stats RecordStats var stats recordStats
walkMatches(records, features, minScore, func(record Record, score float64) { walkMatches(entries, features, minScore, func(record record, score float64) {
stats.compatibility += record.compatibility stats.compatibility += record.compatibility
stats.count++ stats.count++
}) })
@ -57,7 +57,7 @@ func statRecords(records Records, features Features, minScore float64) RecordSta
return stats return stats
} }
func stepRange(bounds Bounds, steps int, callback func(float64)) { func stepRange(bounds queryBounds, steps int, callback func(float64)) {
stepSize := (bounds.max - bounds.min) / float64(steps) stepSize := (bounds.max - bounds.min) / float64(steps)
for i := 0; i < steps; i++ { for i := 0; i < steps; i++ {
@ -69,37 +69,37 @@ func stepRange(bounds Bounds, steps int, callback func(float64)) {
} }
} }
func findRecords(records Records, features Features, minScore float64) { func findRecords(entries records, features featureMap, minScore float64) {
var foundRecords Records var foundRecords records
walkMatches(records, features, minScore, func(record Record, score float64) { walkMatches(entries, features, minScore, func(record record, score float64) {
foundRecords = append(foundRecords, record) foundRecords = append(foundRecords, record)
}) })
sort.Sort(foundRecords) sort.Sort(foundRecords)
} }
func project(records Records, features Features, featureName string, minScore float64, bounds Bounds, steps int) []Projection { func project(entries records, features featureMap, featureName string, minScore float64, bounds queryBounds, steps int) []queryProjection {
sampleFeatures := make(Features) sampleFeatures := make(featureMap)
for key, value := range features { for key, value := range features {
sampleFeatures[key] = value sampleFeatures[key] = value
} }
var projection []Projection var projection []queryProjection
stepRange(bounds, steps, func(sample float64) { stepRange(bounds, steps, func(sample float64) {
sampleFeatures[featureName] = sample sampleFeatures[featureName] = sample
stats := statRecords(records, sampleFeatures, minScore) stats := statRecords(entries, sampleFeatures, minScore)
projection = append(projection, Projection{sample: sample, stats: stats}) projection = append(projection, queryProjection{sample: sample, stats: stats})
}) })
return projection return projection
} }
func computeRecordGeo(records Records, context Context) { func computeRecordGeo(entries records, context queryContext) {
distUserMin := math.MaxFloat64 distUserMin := math.MaxFloat64
distUserMax := 0.0 distUserMax := 0.0
for _, record := range records { for _, record := range entries {
if context.geo.valid { if context.geo.valid {
userPoint := geo.NewPoint(context.geo.latitude, context.geo.longitude) userPoint := geo.NewPoint(context.geo.latitude, context.geo.longitude)
recordPoint := geo.NewPoint(record.geo.latitude, context.geo.longitude) recordPoint := geo.NewPoint(record.geo.latitude, context.geo.longitude)
@ -116,7 +116,7 @@ func computeRecordGeo(records Records, context Context) {
distUserRange := distUserMax - distUserMin distUserRange := distUserMax - distUserMin
for _, record := range records { for _, record := range entries {
nearby := -((record.distanceToUser-distUserMin)/distUserRange - 0.5) * 2.0 nearby := -((record.distanceToUser-distUserMin)/distUserRange - 0.5) * 2.0
accessible := 1.0 - (record.distanceToStn / context.walkingDist) accessible := 1.0 - (record.distanceToStn / context.walkingDist)
@ -131,8 +131,8 @@ func computeRecordGeo(records Records, context Context) {
} }
} }
func computeRecordPopularity(records Records, context Context) { func computeRecordPopularity(entries records, context queryContext) {
for _, record := range records { for _, record := range entries {
historyRows, err := db.Query("SELECT id FROM history WHERE reviewId = (?)", record.id) historyRows, err := db.Query("SELECT id FROM history WHERE reviewId = (?)", record.id)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -152,7 +152,7 @@ func computeRecordPopularity(records Records, context Context) {
log.Fatal(err) log.Fatal(err)
} }
recordProfile := make(Features) recordProfile := make(featureMap)
for groupRows.Next() { for groupRows.Next() {
var categoryId int var categoryId int
var categoryValue float64 var categoryValue float64