Wheel of Fortune
Spin the Wheel of Fortune to win a price.
http://localhost:8080/wheel-of-fortune
This example shows the union feature as described here: ../service-interfaces/value-objects#union-types
Go service
Service interface defintion
package wof
type Trip struct {
Kind string `json:"kind" gotsrpc:"type:'Trip'"`
Name string `json:"name"`
Description string `json:"description"`
}
type (
Species struct {
LandAnimals *LandAnimals `json:"landAnimals,omitempty" gotsrpc:"union"`
WaterAnimals *WaterAnimals `json:"waterAnimals,omitempty" gotsrpc:"union"`
}
LandAnimals string
WaterAnimals string
)
const (
Cat LandAnimals = "cat"
Dog LandAnimals = "dog"
)
const (
Catfish WaterAnimals = "catfish"
Dogfish WaterAnimals = "dogfish"
)
type Pet struct {
Kind string `json:"kind" gotsrpc:"type:'Pet'"`
Name string `json:"name"`
Species Species `json:"species"`
}
type SeatCount int
const (
TwoSeats SeatCount = 2
FiveSeats SeatCount = 5
SevenSeats SeatCount = 7
)
type Car struct {
Kind string `json:"kind" gotsrpc:"type:'Car'"`
Brand string `json:"brand"`
Model string `json:"model"`
Seats SeatCount `json:"seats"`
Power int `json:"power"`
}
type Price struct {
Trip *Trip `json:"trip,omitempty" gotsrpc:"union"`
Car *Car `json:"car,omitempty" gotsrpc:"union"`
Pet *Pet `json:"pet,omitempty" gotsrpc:"union"`
}
type Service interface {
Spin() Price
}
Service implementation
package server
import (
"math/rand"
"runtime"
"time"
"github.com/foomo/gotsrpc-playground/server/services/wof"
)
type wofService struct {
r *rand.Rand
}
func NewWof() wof.Service {
return &wofService{
r: rand.New(rand.NewSource(time.Now().UnixMicro())),
}
}
func (s *wofService) Spin() wof.Price {
// it has to spin for a little time
time.Sleep(time.Second)
switch int(s.r.Float64() * 3) {
case 0:
return wof.Price{
Trip: &wof.Trip{
Kind: "Trip",
Name: "to the moon",
Description: "takes you to the moon",
},
}
case 1:
return wof.Price{
Car: &wof.Car{
Kind: "Car",
Brand: "gocart",
Model: "1.20",
Seats: wof.TwoSeats,
Power: runtime.NumCPU(),
},
}
case 2:
fallthrough
default:
species := wof.Catfish
return wof.Price{
Pet: &wof.Pet{
Kind: "Pet",
Name: "James",
Species: wof.Species{
WaterAnimals: &species,
},
},
}
}
}
Next.js TypeScript client
import { Car } from "@/components/wof/Car";
import { Trip } from "@/components/wof/Trip";
import { Pet } from "@/components/wof/Pet";
import { ServiceClient } from "@/services/generated/client-wof";
import classes from "@/styles/Wof.module.css";
import { useState } from "react";
import { Price } from "@/services/generated/vo-wof";
import { getClientWithTransportLog, useTransportLogStore } from "@/services/transportWithLog";
const NoPriceComp = () => {
return <div>No Price</div>;
};
const getComponentForPrice = (
price?: Price
): React.FunctionComponent<Price> => {
switch (price?.kind) {
case "Car":
return Car as React.FunctionComponent<Price>;
case "Trip":
return Trip as React.FunctionComponent<Price>;
case "Pet":
return Pet as React.FunctionComponent<Price>;
default:
return NoPriceComp;
}
};
const client = getClientWithTransportLog(ServiceClient);
const WheelOfFortune = () => {
const numRunningCalls = useTransportLogStore(
(state) => state.numRunningCalls
);
const [price, setPrice] = useState<Price>(undefined);
const PriceComp = getComponentForPrice(price);
return (
<div>
<aside>This example shows gotsrpc's union feature</aside>
<button
onClick={(_) => {
client.spin().then(setPrice);
setPrice(undefined);
}}
>
spin the wheel of fortune to win a price 🎰
</button>
{numRunningCalls > 0 && <p>the wheel of fortune is spinning ...</p>}
{price && (
<div className={classes.price}>
Your price is a ({price.kind})
<PriceComp {...price} />
</div>
)}
</div>
);
};
export default WheelOfFortune;