feat: add service and model

This commit is contained in:
Jeffrey Duroyon
2020-05-10 23:58:49 +02:00
parent 4369438ff2
commit c8993f1ca3
20 changed files with 89 additions and 29 deletions

View File

@@ -15,4 +15,12 @@ type Database interface {
UpdateUser(*model.User) error
// end: user dao funcs
// start: cage games funcs
GetAllGames() ([]*model.Game, error)
GetGameById(string) (*model.Game, error)
CreateGame(*model.Game) error
DeleteGame(string) error
UpdateGame(*model.Game) error
// end: games dao funcs
}

View File

@@ -0,0 +1 @@
package fake

View File

@@ -0,0 +1 @@
package fake

View File

@@ -0,0 +1 @@
package fake

View File

@@ -0,0 +1 @@
package postgresql

View File

@@ -0,0 +1 @@
package postgresql

View File

@@ -0,0 +1 @@
package postgresql

5
storage/model/cage.go Normal file
View File

@@ -0,0 +1,5 @@
package model
type Cage struct {
Hamsters []*Hamster
}

8
storage/model/game.go Normal file
View File

@@ -0,0 +1,8 @@
package model
type Game struct {
ID string
server Server
Cages []*Cage
SelledHamster []*Hamster
}

155
storage/model/hamster.go Normal file
View File

@@ -0,0 +1,155 @@
package model
import (
"errors"
"fmt"
uuid "github.com/satori/go.uuid"
"hamster-tycoon/randomizer"
)
const (
Full = iota
AlmostFull
Middle
AlmostEmpty
Empty
)
const (
TotalGestationPeriod = 15
MinChild = 5
MaxChild = 9
GestationCooldown = (3 * 7) + 2
GestationMinAge = 10 * 6
MaxAge = 365 * 2
GestationLuck = 70
FEMALE = "F"
MALE = "M"
)
var GlobalHamsterNumber = 1
type Hamster struct {
ID string
Name string
Number int
Sexe string
Age int // in days
Father *Hamster
Mother *Hamster
HungerLevel int8
ThirstLevel int8
Weight float64
Height float64
Alive bool
Selled bool
Gestation bool
GestationPeriod int8
GestationCooldown int8
GestationFather *Hamster
Child []*Hamster
}
func (h *Hamster) Die() {
h.Alive = false
}
func (h *Hamster) Grow() {
if h.Age >= MaxAge {
if randNumber(h.Age-MaxAge, 365) > 364 {
h.Die()
return
}
}
h.Age++
if h.Gestation {
h.GestationPeriod++
} else {
if h.GestationCooldown > 0 {
h.GestationCooldown--
}
}
fmt.Println(h.GestationCooldown)
}
func (h *Hamster) Fuck(another *Hamster) (bool, error) {
if h.Sexe == another.Sexe {
return false, errors.New("can't fuck together")
}
if h.Age < GestationMinAge || another.Age < GestationMinAge {
return false, errors.New("one of the hamster is too young")
}
rand := randNumber(1, 100)
if rand <= GestationLuck {
female, male := func() (*Hamster, *Hamster) {
if h.Sexe == FEMALE {
return h, another
} else {
return another, h
}
}()
female.GestationFather = male
female.Gestation = true
female.GestationPeriod = 0
female.GestationCooldown = TotalGestationPeriod + GestationCooldown
}
return rand <= GestationLuck, nil
}
func Born(father *Hamster, mother *Hamster) ([]*Hamster, error) {
if !mother.Alive || mother.Selled {
return nil, errors.New("the mother is not here")
}
if mother.GestationPeriod != TotalGestationPeriod {
return nil, errors.New("not the time to make child")
}
mother.GestationCooldown = 0
mother.Gestation = false
mother.GestationPeriod = 0
numberOfChild := randNumberChild()
child := make([]*Hamster, numberOfChild)
for i := 0; i < numberOfChild; i++ {
child[i] = &Hamster{
ID: uuid.NewV4().String(),
Name: fmt.Sprintf("Hamster %d", GlobalHamsterNumber),
Number: GlobalHamsterNumber,
Age: 1,
Sexe: randSexe(),
Father: father,
Mother: mother,
HungerLevel: Full,
ThirstLevel: Full,
Alive: true,
Selled: false,
Gestation: false,
GestationPeriod: 0,
GestationCooldown: 30,
}
}
mother.Child = append(mother.Child, child...)
father.Child = append(father.Child, child...)
return child, nil
}
func randNumberChild() int {
return randNumber(MinChild, MaxChild)
}
func randSexe() string {
return func() string {
if randNumber(1, 2) == 2 {
return MALE
} else {
return FEMALE
}
}()
}
func randNumber(min int, max int) int {
return min + randomizer.Rand(max)
}

View File

@@ -0,0 +1,333 @@
package model
import (
"errors"
"hamster-tycoon/randomizer"
"reflect"
"testing"
)
func TestHamster_Die(t *testing.T) {
testCases := []struct {
caseName string
hamster *Hamster
expectedAlive bool
}{
{
caseName: "Should die",
hamster: &Hamster{
Alive: true,
},
expectedAlive: false,
},
{
caseName: "Already die",
hamster: &Hamster{
Alive: false,
},
expectedAlive: false,
},
}
for _, tc := range testCases {
t.Run(tc.caseName, func(t *testing.T) {
tc.hamster.Die()
if tc.hamster.Alive != tc.expectedAlive {
t.Errorf("Die result does not match expectation. \n Got : %t \n Get : %t", tc.expectedAlive, tc.hamster.Alive)
}
})
}
}
func TestHamster_Grow(t *testing.T) {
testCases := []struct {
caseName string
hamster *Hamster
expectedHamster *Hamster
}{
{
caseName: "Age increment",
hamster: &Hamster{
Age: 0,
Alive: true,
},
expectedHamster: &Hamster{
Age: 1,
Alive: true,
},
},
{
caseName: "Gestation decrement",
hamster: &Hamster{
Age: 0,
Gestation: true,
GestationPeriod: 1,
Alive: true,
},
expectedHamster: &Hamster{
Age: 1,
Gestation: true,
GestationPeriod: 2,
Alive: true,
},
},
{
caseName: "Gestation Cooldown doesn't decrement",
hamster: &Hamster{
Age: 0,
Gestation: true,
GestationCooldown: 17,
GestationPeriod: 1,
Alive: true,
},
expectedHamster: &Hamster{
Age: 1,
GestationCooldown: 17,
Gestation: true,
GestationPeriod: 2,
Alive: true,
},
},
{
caseName: "Gestation Cooldown decrement",
hamster: &Hamster{
Age: 0,
Gestation: false,
GestationCooldown: 17,
GestationPeriod: 0,
Alive: true,
},
expectedHamster: &Hamster{
Age: 1,
GestationCooldown: 16,
Gestation: false,
GestationPeriod: 0,
Alive: true,
},
},
{
caseName: "Hamster die",
hamster: &Hamster{
Age: 365 * 3,
Gestation: false,
GestationCooldown: 17,
GestationPeriod: 0,
Alive: true,
},
expectedHamster: &Hamster{
Age: 365 * 3,
Alive: false,
GestationCooldown: 17,
Gestation: false,
GestationPeriod: 0,
},
},
}
for _, tc := range testCases {
t.Run(tc.caseName, func(t *testing.T) {
if tc.hamster.Alive == !tc.expectedHamster.Alive {
randomizer.FakeRandomizer(364)
}
tc.hamster.Grow()
if !reflect.DeepEqual(tc.hamster, tc.expectedHamster) {
t.Errorf("Got %v expect %v", tc.hamster, tc.expectedHamster)
}
})
}
}
func TestHamster_Fuck(t *testing.T) {
testCases := []struct {
caseName string
hamster1 *Hamster
hamster2 *Hamster
expectedResult bool
expectedError error
}{
{
caseName: "Same sexe",
hamster1: &Hamster{
Alive: true,
Sexe: MALE,
Age: GestationMinAge - 1,
},
hamster2: &Hamster{
Alive: true,
Sexe: MALE,
Age: GestationMinAge + 1,
},
expectedResult: false,
expectedError: errors.New("can't fuck together"),
},
{
caseName: "Hamster 1 too young",
hamster1: &Hamster{
Alive: true,
Sexe: MALE,
Age: GestationMinAge - 1,
},
hamster2: &Hamster{
Alive: true,
Sexe: FEMALE,
Age: GestationMinAge + 1,
},
expectedResult: false,
expectedError: errors.New("one of the hamster is too young"),
},
{
caseName: "Hamster 2 too young",
hamster1: &Hamster{
Alive: false,
Sexe: MALE,
Age: GestationMinAge + 1,
},
hamster2: &Hamster{
Alive: true,
Sexe: FEMALE,
Age: GestationMinAge - 1,
},
expectedResult: false,
expectedError: errors.New("one of the hamster is too young"),
},
{
caseName: "Can have sexe and success",
hamster1: &Hamster{
Alive: false,
Sexe: MALE,
Age: GestationMinAge,
},
hamster2: &Hamster{
Alive: true,
Sexe: FEMALE,
Age: GestationMinAge,
},
expectedResult: true,
expectedError: nil,
},
{
caseName: "Can have sexe and fail",
hamster1: &Hamster{
Alive: false,
Sexe: MALE,
Age: GestationMinAge,
},
hamster2: &Hamster{
Alive: true,
Sexe: FEMALE,
Age: GestationMinAge,
},
expectedResult: false,
expectedError: nil,
},
{
caseName: "Can have sexe and success. Inverted female and male",
hamster2: &Hamster{
Alive: false,
Sexe: MALE,
Age: GestationMinAge,
},
hamster1: &Hamster{
Alive: true,
Sexe: FEMALE,
Age: GestationMinAge,
},
expectedResult: true,
expectedError: nil,
},
}
for _, tc := range testCases {
t.Run(tc.caseName, func(t *testing.T) {
if tc.expectedResult {
randomizer.FakeRandomizer(60)
} else {
randomizer.FakeRandomizer(80)
}
bool, err := tc.hamster1.Fuck(tc.hamster2)
if tc.expectedResult != bool {
t.Errorf("Fuck result does not match expectation. \n Got : %t \n Get : %t", tc.expectedResult, bool)
}
if tc.expectedError != nil && err != nil && tc.expectedError.Error() != err.Error() {
t.Errorf("Fuck result does not match expectation. \n Got : %s \n Get : %s", tc.expectedError, err)
}
if tc.expectedError == nil && err != nil {
t.Errorf("Fuck result does not match expectation. \n Got error : %s ", err)
}
if tc.expectedResult {
var female *Hamster
if FEMALE == tc.hamster1.Sexe {
female = tc.hamster1
} else {
female = tc.hamster2
}
if !female.Gestation {
t.Errorf("Female is not in gestation")
}
if female.GestationPeriod != 0 {
t.Errorf("Gestation period doesn't have been reseted")
}
if female.GestationCooldown != TotalGestationPeriod+GestationCooldown {
t.Errorf("Gestation period doesn't have been reseted")
}
}
})
}
}
func Test_randSexe(t *testing.T) {
tests := []struct {
name string
want string
fakeGen int
}{
{
name: "Should be a male",
fakeGen: 1,
want: MALE,
},
{
name: "Should be a female",
fakeGen: 0,
want: FEMALE,
},
}
for _, tt := range tests {
randomizer.FakeRandomizer(tt.fakeGen)
if got := randSexe(); got != tt.want {
t.Errorf("%q. randSexe() = %v, want %v", tt.name, got, tt.want)
}
}
}
func Test_randNumber(t *testing.T) {
type args struct {
min int
max int
}
tests := []struct {
name string
args args
fakeGen int
want int
}{
{
name: "Should add min to result",
args: args{
min: 1,
max: 2,
},
fakeGen: 0,
want: 1,
},
}
for _, tt := range tests {
randomizer.FakeRandomizer(tt.fakeGen)
if got := randNumber(tt.args.min, tt.args.max); got != tt.want {
t.Errorf("%q. randNumber() = %v, want %v", tt.name, got, tt.want)
}
}
}

5
storage/model/server.go Normal file
View File

@@ -0,0 +1,5 @@
package model
type Server struct {
ID string
}

View File

@@ -1,6 +1,8 @@
package model
import "time"
import (
"time"
)
type User struct {
UserEditable
@@ -8,6 +10,7 @@ type User struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt *time.Time `json:"updatedAt"`
GoogleId string `json:"-"`
Games []Game
}
type UserEditable struct {