Commit 9eff758
Changed files (4)
client.go
@@ -2,13 +2,10 @@ package main
import (
"bufio"
- "encoding/json"
"flag"
"fmt"
"github.com/BurntSushi/toml"
- "io/ioutil"
"log"
- "net/http"
"os"
"strconv"
"strings"
@@ -20,6 +17,8 @@ type CLIENT_CONFIG struct {
SERVER string
// PORT is the port on which to connect
PORT int
+ // SERVER_URL contains the url to access the server, including the protocol
+ SERVER_URL string
// USE_HTTPS determines if the client should connect using HTTPS
USE_HTTPS bool
// USER defines the user that is in control of this session
@@ -32,35 +31,17 @@ var clientConfig CLIENT_CONFIG
func loadClientConfiguration(cfgFile string) CLIENT_CONFIG {
log.Printf("Loading configuration from %s.", cfgFile)
_, err := toml.DecodeFile(cfgFile, &clientConfig)
- if err != nil {
- log.Fatalf("Could not read configuration file: %+v\n", err.Error())
- os.Exit(EXIT_CODE.FILE_IO_ERROR)
- }
- return clientConfig
-}
-
-// getRecordFromServer retrieves a record from the server
-func getRecordFromServer(client *http.Client, config CLIENT_CONFIG, numQuestions int) ([]Record, error) {
- var serverURL string
- // allows adding configuration for port specific (ie HTTPS) requests
- switch config.PORT {
+ switch clientConfig.PORT {
case 0:
- serverURL = config.SERVER
+ clientConfig.SERVER_URL = clientConfig.SERVER
default:
- serverURL = "http://" + config.SERVER + ":" + strconv.Itoa(config.PORT)
- }
- resp, err := client.Get(serverURL + API_ROOT + "/test" + "?questions=" + strconv.Itoa(numQuestions))
- if err != nil {
- return nil, err
+ clientConfig.SERVER_URL = "http://" + clientConfig.SERVER + ":" + strconv.Itoa(clientConfig.PORT)
}
- defer resp.Body.Close()
- var recordArray []Record
- data, err := ioutil.ReadAll(resp.Body)
if err != nil {
- return nil, err
+ log.Fatalf("Could not read configuration file: %+v\n", err.Error())
+ os.Exit(EXIT_CODE.FILE_IO_ERROR)
}
- err = json.Unmarshal(data, &recordArray)
- return recordArray, err
+ return clientConfig
}
// initUserSession starts the interactive prompt for the user
@@ -72,6 +53,10 @@ func initUserSession() {
var err error
reader := bufio.NewReader(os.Stdin)
for {
+ if clientConfig.USER == "" {
+ fmt.Print("\nUsername is blank. Setting to 'anonymous.' Use 'user' to change user name.")
+ clientConfig.USER = "anonymous"
+ }
fmt.Printf("\n:> ")
input, _ = reader.ReadString('\n')
args := strings.Fields(input)
@@ -95,6 +80,12 @@ func ExecuteClient() {
clientConfig.SERVER = "127.0.0.1"
clientConfig.PORT = 80
clientConfig.USE_HTTPS = false
+ switch clientConfig.PORT {
+ case 0:
+ clientConfig.SERVER_URL = clientConfig.SERVER
+ default:
+ clientConfig.SERVER_URL = "http://" + clientConfig.SERVER + ":" + strconv.Itoa(clientConfig.PORT)
+ }
filePath := flag.String("file", "", "defines a path to the configuration file")
flag.Parse()
if strings.Compare(*filePath, "") != 0 {
command.go
@@ -2,7 +2,10 @@ package main
import (
"bufio"
+ "bytes"
+ "encoding/json"
"fmt"
+ "io/ioutil"
"net/http"
"os"
"strconv"
@@ -82,12 +85,61 @@ func init() {
commandArray = append(commandArray, helpCommand)
}
+// walks the user through the test questions
+// this function updates the records with the user responses
+func runTest(recordArray []ClientRecord) []ClientRecord {
+ reader := bufio.NewReader(os.Stdin)
+ var responseArray []ClientRecord
+ for i, record := range recordArray {
+ fmt.Printf("%d) %s\n", i+1, record.Question)
+ input, _ := reader.ReadString('\n')
+ input = strings.TrimSpace(input)
+ if strings.Compare(input, record.Answer) == 0 {
+ fmt.Println("Correct.")
+ recordArray[i].AnsweredCorrectly = true
+ } else if strings.Compare(input, "exit") == 0 {
+ return responseArray
+ } else {
+ fmt.Printf("Incorrect. Correct answer was: %s\n", record.Answer)
+ recordArray[i].ClientAnswer = input
+ }
+ }
+ return responseArray
+}
+
+// postRecordsToServer sends the client responses back to the server
+func postRecordsToServer(client *http.Client, recordArray *[]ClientRecord) error {
+ data, err := json.Marshal(recordArray)
+ if err != nil {
+ return err
+ }
+ _, err = client.Post(clientConfig.SERVER_URL+API_ROOT+"/test?username="+clientConfig.USER, "", bytes.NewBuffer(data))
+ return err
+}
+
+// getRecordFromServer retrieves a record from the server
+func getRecordFromServer(client *http.Client, config CLIENT_CONFIG, numQuestions int) ([]ClientRecord, error) {
+ // allows adding configuration for port specific (ie HTTPS) requests
+ resp, err := client.Get(clientConfig.SERVER_URL + API_ROOT + "/test" + "?questions=" + strconv.Itoa(numQuestions))
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ var recordArray []ClientRecord
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(data, &recordArray)
+ return recordArray, err
+}
+
// executeTest runs a user through a test
+// from retrieving the records to returning the answers
func executeTest(args []string) error {
client := &http.Client{}
- var recordArray []Record
+ var recordArray []ClientRecord
var err error
- var input string
questions := 20
if len(args) > 0 {
questions, err = strconv.Atoi(args[0])
@@ -99,17 +151,6 @@ func executeTest(args []string) error {
if err != nil {
return fmt.Errorf("Error while request from server: %+v", err)
}
- reader := bufio.NewReader(os.Stdin)
- for i, record := range recordArray {
- fmt.Printf("%d) %s\n", i+1, record.Question)
- input, _ = reader.ReadString('\n')
- if strings.Compare(strings.TrimSpace(input), record.Answer) == 0 {
- fmt.Println("Correct.")
- } else if strings.Compare(strings.TrimSpace(input), "exit") == 0 {
- return nil
- } else {
- fmt.Printf("Incorrect. Correct answer was: %s\n", record.Answer)
- }
- }
- return nil
+ runTest(recordArray)
+ return postRecordsToServer(client, &recordArray)
}
serverHandlers.go
@@ -2,6 +2,7 @@ package main
import (
"encoding/json"
+ "fmt"
"log"
"math/rand"
"net/http"
@@ -9,7 +10,7 @@ import (
)
// handleRequestForTest provides a JSON formatted test for the client
-func handleRequestForTest(writer http.ResponseWriter, request *http.Request) {
+func handleRequestForTest(writer http.ResponseWriter, request *http.Request) error {
var giveRecords []Record
var err error
questions := request.FormValue("questions")
@@ -19,10 +20,16 @@ func handleRequestForTest(writer http.ResponseWriter, request *http.Request) {
}
data, err := json.Marshal(giveRecords)
if err != nil {
- log.Printf("Error building questions: %+v", err)
+ return fmt.Errorf("Error building questions: %+v", err)
}
writer.Write(data)
- log.Printf("Gave %d questions to %s", numQuestions, request.RemoteAddr)
+ log.Printf("Gave %d questions to %s", len(giveRecords), request.RemoteAddr)
+ return nil
+}
+
+// handlePostingTest receives a client's test results, and then stores them
+func handlePostingTest(writer http.ResponseWriter, request *http.Request) error {
+ return nil
}
// handleTestRequests creates an array of records for the client
@@ -34,9 +41,15 @@ func handleTestQueries(writer http.ResponseWriter, request *http.Request) {
switch request.Method {
case "POST":
log.Printf("Client posting test: %+v\tvia %+v", request.RemoteAddr, request.UserAgent())
+ if err := handlePostingTest(writer, request); err != nil {
+ log.Printf("Error while receiving test: %+v", err)
+ }
case "GET":
log.Printf("Client requested test: %+v\tvia %+v", request.RemoteAddr, request.UserAgent())
- handleRequestForTest(writer, request)
+ if err := handleRequestForTest(writer, request); err != nil {
+ log.Printf("Error while serving test: %+v", err)
+ }
+
}
}
structures.go
@@ -23,3 +23,10 @@ type Record struct {
Category string
ID int
}
+
+// ClientRecord stores the client response to a particular record
+type ClientRecord struct {
+ Record
+ ClientAnswer string
+ AnsweredCorrectly bool
+}