generated from VLADIMIR/template
storytelling
This commit is contained in:
@@ -26,3 +26,5 @@ go.work
|
|||||||
go.sum
|
go.sum
|
||||||
|
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
.VSCodeCounter/
|
||||||
|
|||||||
Vendored
+1
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"Аркхема",
|
||||||
"pgxpool",
|
"pgxpool",
|
||||||
"timestamppb"
|
"timestamppb"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -4,12 +4,20 @@ go 1.25.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
|
||||||
|
github.com/stretchr/testify v1.11.1
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8
|
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8
|
||||||
google.golang.org/grpc v1.64.0
|
google.golang.org/grpc v1.64.0
|
||||||
google.golang.org/protobuf v1.34.1
|
google.golang.org/protobuf v1.34.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require github.com/vearutop/statigz v1.4.0 // indirect
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/rogpeppe/go-internal v1.15.0 // indirect
|
||||||
|
github.com/vearutop/statigz v1.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package storytelling
|
||||||
|
|
||||||
|
type IStory interface {
|
||||||
|
GetStory(scenario *Story, codes []string) *Story
|
||||||
|
}
|
||||||
|
|
||||||
|
// История - это набор точек
|
||||||
|
type Story struct {
|
||||||
|
|
||||||
|
// Список точек
|
||||||
|
Places []*Place `json:"places"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Точка - что-то куда можно сходить
|
||||||
|
// Это может быть место - аптека, остановка, площадь...
|
||||||
|
// Это может быть персонаж - пострадавший, продавец, полицейский...
|
||||||
|
// Это может быть описание действия игрока - ответ на вопрос, реакция на выбитую дверь...
|
||||||
|
type Place struct {
|
||||||
|
|
||||||
|
// Код - то что вбивает игрок
|
||||||
|
Code string `json:"code"`
|
||||||
|
|
||||||
|
// Название места, имя персонажа, заданный игроком вопрос...
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Текст - получаемая текстовая информация
|
||||||
|
Text string `json:"text"`
|
||||||
|
|
||||||
|
// Картинка - получаемая визуальная информация
|
||||||
|
Image string `json:"image"`
|
||||||
|
|
||||||
|
// Признак скрытой карточки - некоторые места изначально не доступны
|
||||||
|
Hidden bool `json:"hidden"`
|
||||||
|
|
||||||
|
// Приложения - получаемые улики
|
||||||
|
Applications []*Application `json:"applications,omitempty"`
|
||||||
|
|
||||||
|
// Двери к другим точкам - действия или диалоги, открывающие другие точки
|
||||||
|
Doors []*Door `json:"doors"`
|
||||||
|
|
||||||
|
// Получаемые ключи - ключи используются для получения доступа к скрытым дверям
|
||||||
|
Keys []*Key `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Приложение - улика
|
||||||
|
// Это может быть оружие, отпечатки, фотография...
|
||||||
|
type Application struct {
|
||||||
|
|
||||||
|
// Название улики
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Картинка
|
||||||
|
Image string `json:"image"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Дверь - действие или диалог
|
||||||
|
type Door struct {
|
||||||
|
|
||||||
|
// Код
|
||||||
|
Code string `json:"code"`
|
||||||
|
|
||||||
|
// Название - заданный вопрос, проделанное действие...
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Некоторые двери изначально не доступны
|
||||||
|
// Ключи требуемые для получения доступа к скрытым дверям
|
||||||
|
// Если указаны ключи то дверь считается скрытой
|
||||||
|
Keys []*Key `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Аналог карт допуска в "Тайны Аркхема"
|
||||||
|
type Key struct {
|
||||||
|
|
||||||
|
// Название
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
package storytelling
|
||||||
|
|
||||||
|
type story struct{}
|
||||||
|
|
||||||
|
func NewStory() IStory {
|
||||||
|
return &story{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *story) GetStory(
|
||||||
|
scenario *Story,
|
||||||
|
codes []string,
|
||||||
|
) *Story {
|
||||||
|
story := &Story{}
|
||||||
|
keys := map[string]struct{}{}
|
||||||
|
codesWithUseActions := map[string]struct{}{}
|
||||||
|
codesHidden := map[string]struct{}{}
|
||||||
|
for i, code := range codes {
|
||||||
|
var prevPlace *Place
|
||||||
|
if i > 0 {
|
||||||
|
prevPlace, _ = s.findPlace(scenario, codes[i-1])
|
||||||
|
}
|
||||||
|
currentPlace, _ := s.findPlace(scenario, codes[i])
|
||||||
|
var nextPlace *Place
|
||||||
|
if i < len(codes)-1 {
|
||||||
|
nextPlace, _ = s.findPlace(scenario, codes[i+1])
|
||||||
|
}
|
||||||
|
// Если следующая точка это открытие двери в текущей точке, то текущая точка считается использованной для действия
|
||||||
|
if nextPlace != nil && currentPlace != nil {
|
||||||
|
openDoor := false
|
||||||
|
for _, door := range currentPlace.Doors {
|
||||||
|
if door.Code == nextPlace.Code {
|
||||||
|
codesWithUseActions[currentPlace.Code] = struct{}{}
|
||||||
|
openDoor = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if openDoor {
|
||||||
|
// Запрещаем смотреть не выбранные действия
|
||||||
|
for _, door := range currentPlace.Doors {
|
||||||
|
if door.Code != nextPlace.Code {
|
||||||
|
codesHidden[door.Code] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Собираем ключи
|
||||||
|
if currentPlace != nil {
|
||||||
|
for _, key := range currentPlace.Keys {
|
||||||
|
keys[key.Name] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
place, ok := s.findResultPlace(scenario, code, prevPlace, codesHidden)
|
||||||
|
if !ok {
|
||||||
|
story.Places = append(story.Places, s.buildNotFoundPlace(code))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
story.Places = append(
|
||||||
|
story.Places,
|
||||||
|
s.mapPlace(place, nextPlace, codesWithUseActions, keys),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return story
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *story) findPlace(
|
||||||
|
scenario *Story,
|
||||||
|
code string,
|
||||||
|
) (*Place, bool) {
|
||||||
|
for _, place := range scenario.Places {
|
||||||
|
if place.Code == code {
|
||||||
|
return place, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *story) findResultPlace(
|
||||||
|
scenario *Story,
|
||||||
|
code string,
|
||||||
|
prevPlace *Place,
|
||||||
|
codesHidden map[string]struct{},
|
||||||
|
) (*Place, bool) {
|
||||||
|
if _, ok := codesHidden[code]; ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
open := false
|
||||||
|
if prevPlace != nil {
|
||||||
|
for _, door := range prevPlace.Doors {
|
||||||
|
if door.Code == code {
|
||||||
|
open = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, place := range scenario.Places {
|
||||||
|
if place.Code == code {
|
||||||
|
if place.Hidden && !open {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return place, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *story) buildNotFoundPlace(code string) *Place {
|
||||||
|
return &Place{
|
||||||
|
Code: code,
|
||||||
|
Name: "Не найдено",
|
||||||
|
Text: "Такой точки не существует.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *story) mapPlace(
|
||||||
|
place *Place,
|
||||||
|
nextPlace *Place,
|
||||||
|
codesWithUseActions map[string]struct{},
|
||||||
|
keys map[string]struct{},
|
||||||
|
) *Place {
|
||||||
|
var applications []*Application
|
||||||
|
if len(place.Applications) > 0 {
|
||||||
|
applications = make([]*Application, 0, len(place.Applications))
|
||||||
|
for _, application := range place.Applications {
|
||||||
|
applications = append(
|
||||||
|
applications,
|
||||||
|
&Application{
|
||||||
|
Name: application.Name,
|
||||||
|
Image: application.Image,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var doors []*Door
|
||||||
|
_, useAction := codesWithUseActions[place.Code]
|
||||||
|
if len(place.Doors) > 0 && !useAction {
|
||||||
|
doors = make([]*Door, 0, len(place.Doors))
|
||||||
|
for _, door := range place.Doors {
|
||||||
|
if nextPlace != nil {
|
||||||
|
if door.Code != nextPlace.Code {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasKeys := true
|
||||||
|
for _, doorKey := range door.Keys {
|
||||||
|
if _, ok := keys[doorKey.Name]; !ok {
|
||||||
|
hasKeys = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasKeys {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
doors = append(
|
||||||
|
doors,
|
||||||
|
&Door{
|
||||||
|
Code: door.Code,
|
||||||
|
Name: door.Name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(doors) == 0 {
|
||||||
|
doors = nil
|
||||||
|
}
|
||||||
|
return &Place{
|
||||||
|
Code: place.Code,
|
||||||
|
Name: place.Name,
|
||||||
|
Text: place.Text,
|
||||||
|
Image: place.Image,
|
||||||
|
Applications: applications,
|
||||||
|
Doors: doors,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,677 @@
|
|||||||
|
package storytelling
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_story_GetStory(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
scenario *Story
|
||||||
|
codes []string
|
||||||
|
want *Story
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Попытка получить несуществующую точку",
|
||||||
|
scenario: &Story{},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Не найдено",
|
||||||
|
Text: "Такой точки не существует.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение точки",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение 2 точек",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки Ы",
|
||||||
|
Text: "Текст точки Ы.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки Д",
|
||||||
|
Text: "Текст точки Д.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Д"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки Ы",
|
||||||
|
Text: "Текст точки Ы.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки Д",
|
||||||
|
Text: "Текст точки Д.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение точки с картинкой",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Image: "image.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Image: "image.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Попытка получить скрытую точку",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Не найдено",
|
||||||
|
Text: "Такой точки не существует.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение точки с уликой",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Applications: []*Application{
|
||||||
|
{
|
||||||
|
Name: "Название улики",
|
||||||
|
Image: "image.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Applications: []*Application{
|
||||||
|
{
|
||||||
|
Name: "Название улики",
|
||||||
|
Image: "image.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение точки с действием",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Не открываем скрытую точку действием",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Д"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Открываем скрытую точку действием",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Ы-1"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Не открываем скрытую точку действием, а потом возвращаемся",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Д", "Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Открываем скрытую точку действием, а потом возвращаемся",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Ы-1", "Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение точки со скрытым действием",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение точки с ключом",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Получение ключа и открытие скрытого действия",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Д"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "После выбора одного из действий остальные не доступны",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-2",
|
||||||
|
Name: "Действие 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-2",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы", "Ы-1", "Ы-2", "Ы", "Ы-2"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-2",
|
||||||
|
Name: "Не найдено",
|
||||||
|
Text: "Такой точки не существует.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-2",
|
||||||
|
Name: "Не найдено",
|
||||||
|
Text: "Такой точки не существует.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Если ключей не хватает то скрытые двери не видим",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Действие",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ключ 2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы-1", "Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Собираем ключи и видим скрытые двери",
|
||||||
|
scenario: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ 1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-2",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ 2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Действие",
|
||||||
|
Keys: []*Key{
|
||||||
|
{
|
||||||
|
Name: "ключ 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ключ 2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codes: []string{"Ы-1", "Ы-2", "Ы"},
|
||||||
|
want: &Story{
|
||||||
|
Places: []*Place{
|
||||||
|
{
|
||||||
|
Code: "Ы-1",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы-2",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Code: "Ы",
|
||||||
|
Name: "Название точки",
|
||||||
|
Text: "Текст точки.",
|
||||||
|
Doors: []*Door{
|
||||||
|
{
|
||||||
|
Code: "Д",
|
||||||
|
Name: "Действие",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := NewStory().GetStory(tt.scenario, tt.codes)
|
||||||
|
assert.Equal(t, got, tt.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user