Commit 6692814
Changed files (3)
question.go
@@ -13,7 +13,7 @@ import (
// this question is a member of
func assignCategory(category string, record *Record) {
if _, inMap := recordMap[category]; inMap != true {
- recordMap[category] = []Record{}
+ recordMap[category] = map[int]Record{}
categoryKeys = append(categoryKeys, category)
record.Category = len(categoryKeys) - 1
} else {
@@ -41,7 +41,8 @@ func parseLine(line string) error {
record.Answer = strings.TrimSpace(tokens[1])
category := strings.TrimSpace(strings.ToLower(tokens[2]))
assignCategory(category, &record)
- recordMap[category] = append(recordMap[category], record)
+ key := len(recordMap[category]) + 1
+ recordMap[category][key] = record
return nil
}
serverHandlers.go
@@ -19,18 +19,40 @@ import (
var userTests map[string][]ClientTest
var userTestsLock = sync.RWMutex{}
+// getRecordForCategory returns a record for the specified category
+// it moves the now used record to the usedRecordMap, and updates
+// recordMap to reflect the change
+func getRecordForCategory(category string) Record {
+ mapLock.Lock()
+ defer mapLock.Unlock()
+ if len(recordMap[category]) == 0 {
+ recordMap[category] = usedRecordMap[category]
+ usedRecordMap[category] = map[int]Record{}
+ }
+ recordIndex := rand.Intn(len(recordMap[category]))
+ record := recordMap[category][recordIndex]
+ delete(recordMap[category], recordIndex)
+ if usedRecordMap[category] == nil {
+ usedRecordMap[category] = map[int]Record{}
+ }
+ usedRecordMap[category][len(usedRecordMap[category])] = record
+ return record
+}
+
// buildRecordArray builds an array of Records based on the parameter criteria
func buildRecordArray(numQuestions int, categories []int) []Record {
- var keyIndex, valueIndex int
+ var keyIndex int
var recordArray = []Record{}
for i := 0; i < numQuestions; i++ {
if categories == nil {
keyIndex = rand.Intn(len(categoryKeys))
} else {
keyIndex = categories[rand.Intn(len(categories))]
+ if keyIndex >= len(categoryKeys) {
+ return nil
+ }
}
- valueIndex = rand.Intn(len(recordMap[categoryKeys[keyIndex]]))
- recordArray = append(recordArray, recordMap[categoryKeys[keyIndex]][valueIndex])
+ recordArray = append(recordArray, getRecordForCategory(categoryKeys[keyIndex]))
}
return recordArray
}
structures.go
@@ -1,5 +1,7 @@
package main
+import "sync"
+
// API_ROOT defines the root path for the web api interface
const API_ROOT = "/api"
@@ -7,7 +9,15 @@ const API_ROOT = "/api"
// categorical buckets. the category serves as
// the keyname. the map is populated through the
// loadRecords function call.
-var recordMap map[string][]Record
+var recordMap map[string]map[int]Record
+
+// usedRecordMap contains the questions that have
+// already been used. when recordMap is empty,
+// usedRecordMap replaces it.
+var usedRecordMap map[string]map[int]Record
+
+// mapLock locks the maps to prevent concurrency issues
+var mapLock *sync.Mutex
// categoryKeys contains the list of categories
// available from loading the questions.
@@ -106,5 +116,7 @@ func (cSem *CountingSemaphore) SetCapacity(cap int) {
}
func init() {
- recordMap = map[string][]Record{}
+ recordMap = map[string]map[int]Record{}
+ usedRecordMap = map[string]map[int]Record{}
+ mapLock = &sync.Mutex{}
}