diff --git a/.docker/Dockerfile b/.docker/Dockerfile new file mode 100644 index 0000000..b8b774f --- /dev/null +++ b/.docker/Dockerfile @@ -0,0 +1,17 @@ +# Start with a base image containing golang runtime +FROM golang:1.20 + +# Set the working directory in the container +WORKDIR /go/src/app + +# Copy the go.mod and go.sum files +COPY go.mod go.sum ./ + +# Download the dependencies +RUN go mod download + +# Copy the current directory contents into the container at /go/src/app +COPY ../ . + +EXPOSE 8080 +EXPOSE 8000 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cdf6221 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: "3.9" +services: + godip-development: + build: + context: . + dockerfile: .docker/Dockerfile + container_name: godip-development + ports: + - "8080:8080" + - "8000:8000" + volumes: + - .:/go/src/app + tty: true diff --git a/gae/router.go b/gae/router.go index 4a4bcd4..56309e0 100644 --- a/gae/router.go +++ b/gae/router.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/zond/godip" "github.com/zond/godip/variants" "google.golang.org/appengine" ) @@ -22,6 +23,7 @@ func preflight(w http.ResponseWriter, r *http.Request) { func resolve(w http.ResponseWriter, r *http.Request) { corsHeaders(w) + variantName := mux.Vars(r)["variant"] variant, found := variants.Variants[variantName] if !found { @@ -51,8 +53,55 @@ func resolve(w http.ResponseWriter, r *http.Request) { } } +func resolveWithOptions(w http.ResponseWriter, r *http.Request) { + corsHeaders(w) + + variantName := mux.Vars(r)["variant"] + variant, found := variants.Variants[variantName] + if !found { + http.Error(w, fmt.Sprintf("Variant %q not found", variantName), 404) + return + } + p := &Phase{} + if err := json.NewDecoder(r.Body).Decode(p); err != nil { + http.Error(w, err.Error(), 400) + return + } + state, err := p.State(variant) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + if err = state.Next(); err != nil { + http.Error(w, err.Error(), 500) + return + } + + nextPhase := NewPhase(state) + + options := map[godip.Nation]godip.Options{} + for _, nation := range state.Graph().Nations() { + options[nation] = state.Phase().Options(state, nation) + } + + response := struct { + Phase *Phase `json:"phase"` + Options map[godip.Nation]godip.Options `json:"options"` + }{ + Phase: nextPhase, + Options: options, + } + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + if err = json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, err.Error(), 500) + return + } +} + func start(w http.ResponseWriter, r *http.Request) { corsHeaders(w) + variantName := mux.Vars(r)["variant"] variant, found := variants.Variants[variantName] if !found { @@ -65,6 +114,7 @@ func start(w http.ResponseWriter, r *http.Request) { return } phase := NewPhase(state) + w.Header().Set("Content-Type", "application/json; charset=UTF-8") if err = json.NewEncoder(w).Encode(phase); err != nil { http.Error(w, err.Error(), 500) @@ -72,6 +122,41 @@ func start(w http.ResponseWriter, r *http.Request) { } } +func startWithOptions(w http.ResponseWriter, r *http.Request) { + corsHeaders(w) + + variantName := mux.Vars(r)["variant"] + variant, found := variants.Variants[variantName] + if !found { + http.Error(w, fmt.Sprintf("Variant %q not found", variantName), 404) + return + } + state, err := variant.Start() + if err != nil { + http.Error(w, err.Error(), 500) + return + } + phase := NewPhase(state) + + options := map[godip.Nation]godip.Options{} + for _, nation := range state.Graph().Nations() { + options[nation] = state.Phase().Options(state, nation) + } + response := struct { + Phase *Phase `json:"phase"` + Options map[godip.Nation]godip.Options `json:"options"` + }{ + Phase: phase, + Options: options, + } + + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + if err = json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, err.Error(), 500) + return + } +} + func listVariants(w http.ResponseWriter, r *http.Request) { corsHeaders(w) w.Header().Set("Content-Type", "application/json; charset=UTF-8") @@ -86,7 +171,9 @@ func main() { r.Methods("OPTIONS").HandlerFunc(preflight) variants := r.Path("/{variant}").Subrouter() variants.Methods("POST").HandlerFunc(resolve) + variants.Path("/resolve-with-options").Methods("POST").HandlerFunc(resolveWithOptions) variants.Methods("GET").HandlerFunc(start) + r.Path("/start-with-options/{variant}").Methods("GET").HandlerFunc(startWithOptions) r.Path("/").HandlerFunc(listVariants) http.Handle("/", r) appengine.Main()