Uploads files to new contract

This commit is contained in:
Anastasia Avsyukevich 2025-01-17 20:17:55 +00:00
parent 8f689517c7
commit 4bffaf5fb8
4 changed files with 327 additions and 0 deletions

5
TestContract/go.mod Normal file
View file

@ -0,0 +1,5 @@
module TestContract
go 1.22
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20241223145456-80e18222bca2

2
TestContract/go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20241223145456-80e18222bca2 h1:4Bfi6A1kPpaTDuwbDVc6x+R4WXgoNN9wIq6XobDlXHs=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20241223145456-80e18222bca2/go.mod h1:kVLzmbeJJdbIPF2bUYhD8YppIiLXnRQj5yqNZvzbOL0=

309
TestContract/main.go Normal file
View file

@ -0,0 +1,309 @@
package TestContract
import (
"fmt"
"github.com/google/uuid"
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
)
var notificationName string
// init initializes notificationName before calling any other smart-contract method
func init() {
notificationName = "Hello world!"
}
// RuntimeNotify sends runtime notification with "Hello world!" name
func RuntimeNotify(args []any) {
runtime.Notify(notificationName, args)
}
// RoomStatusWaiting created room wait for join all players
// todo описать фазы
const (
RoomStatusWaiting = "waiting"
// RoomStatusGameIsStarted todo мне не нравится это название фазы. оно должно описывать промежуточное состояние
//мб RoomStatusGaming
// еще до задачи вопроса и после завершения предыдущего раунда
RoomStatusGameIsStarted = "game_is_going"
RoomStatusRoundIsStarted = "round_is_started"
RoomStatusVoting = "voting"
RoomStatusFinished = "finished"
)
type Room struct {
Id string
Host interop.Hash160
Status string
PrizePool int
CountWinners int // ??? //мне кажется норм инт да, они там везде интом оперируют это даже в доке есть
Players []Player
Rounds []Round
}
type Round struct {
number int // Sequence number of round
question string
answers []Answer
}
type Answer struct {
wallet interop.Hash160
answer string
votes int
answerIdx int // Index of sent answer to user - это что, кол-во данных ответов на вопрос?
}
type Player struct {
Wallet interop.Hash160 //roundsWon - сколько раундов выиграл - мы тут не храним в итоге?
}
func getRoom(ctx storage.Context, roomId string) *Room {
var roomData = storage.Get(ctx, []byte("room:"+roomId))
if roomData == nil {
panic("Room with roomId=" + roomId + " not found")
}
return roomData.(*Room)
}
func getSender() interop.Hash160 {
return runtime.GetScriptContainer().Sender
}
func CreateRoom(host interop.Hash160, countWinners int) string {
var ctx = storage.GetContext()
var id = uuid.NewString()
var room = Room{
Id: id,
Host: host,
Status: RoomStatusWaiting,
PrizePool: 0,
CountWinners: countWinners,
Players: []Player{},
Rounds: []Round{},
}
storage.Put(ctx, []byte("room:"+id), room)
return id
//нужно добавить списание денег
}
func JoinRoom(roomId string, wallet interop.Hash160) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
if room.Status != RoomStatusWaiting {
return false //Player cannot join started room
}
for _, player := range room.Players {
if player.Wallet.Equals(wallet) {
return false // Player already joined room
}
}
var player = Player{Wallet: wallet}
room.Players = append(room.Players, player)
storage.Put(ctx, []byte("room:"+roomId), room)
return true
//нужно добавить списание денег
}
func StartGame(roomId string, wallet interop.Hash160) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can start game, room status must be is waiting and players count must be > count winners
if room.Host.Equals(wallet) || room.Status != RoomStatusWaiting || len(room.Players) <= room.CountWinners {
return false //тут же вроде наоборот не equals
}
room.Status = RoomStatusGameIsStarted
storage.Put(ctx, []byte("room:"+roomId), room)
return true
}
func AskQuestion(roomId string, wallet interop.Hash160, question string) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can ask question, room status must be game is started
if room.Host.Equals(wallet) || room.Status != RoomStatusGameIsStarted {
return false //тут же вроде наоборот не equals
}
newRound := Round{
number: len(room.Rounds) + 1,
question: question,
answers: []Answer{},
}
room.Rounds = append(room.Rounds, newRound)
storage.Put(ctx, []byte("room:"+roomId), room)
return true
}
// todo отсюда я начал писать
func StartQuestion(roomId string) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can start question, room status must be game is started
if !room.Host.Equals(getSender()) || room.Status != RoomStatusGameIsStarted {
return false
}
room.Status = RoomStatusRoundIsStarted
for _, player := range room.Players {
var question = room.Rounds[len(room.Rounds)-1].question
sendMessageToPlayer(question, player)
}
storage.Put(ctx, []byte("room:"+roomId), room)
return true
} //тут еще про nns надо не забыть
func SendAnswer(roomId string, answer string) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only player can send answer, room status must be round is started
if roomContains(room.Players, getSender()) || room.Status != RoomStatusRoundIsStarted {
return false
}
newAnswer := Answer{
getSender(),
answer,
0,
-1,
}
room.Rounds[len(room.Rounds)-1].answers = append(room.Rounds[len(room.Rounds)-1].answers, newAnswer)
storage.Put(ctx, []byte("room:"+roomId), room)
return true
}
// todo проверка отправки ответа (от каждого участника если отправлен ответ, то макс один)
func roomContains(slice []Player, item interop.Hash160) bool {
for _, v := range slice {
if v.Wallet.Equals(item) {
return true
}
}
return false
}
func EndQuestion(roomId string) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can end question, room status must be round is started
if !room.Host.Equals(getSender()) || room.Status != RoomStatusRoundIsStarted {
return false
}
room.Status = RoomStatusVoting
var round = room.Rounds[len(room.Rounds)-1]
var result string
for i, answer := range round.answers {
// todo временный комментарий: проставляем индексы ответам как их отправили в вывод, чтобы потом можно было соотнести
// интовый голос за ответ с игроком
answer.answerIdx = i
result += fmt.Sprintf("%d: %s\n", i, answer.answer)
}
for _, player := range room.Players {
sendMessageToPlayer(result, player)
}
storage.Put(ctx, []byte("room:"+roomId), room)
return true
}
func ChooseAnswer(roomId string, answerIdx int) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can choose answer, room status must be voting
if !room.Host.Equals(getSender()) || room.Status != RoomStatusVoting {
return false
}
var round = room.Rounds[len(room.Rounds)-1]
for _, answer := range round.answers {
if answer.answerIdx == answerIdx {
answer.votes += 1
}
}
storage.Put(ctx, []byte("room:"+roomId), room)
return true
}
func sendMessageToPlayer(message string, player Player) {
// todo
}
// todo можно прям сюда подсовывать ссылку на другой контракт кастомный и дефолт реализацию оставить в методе, а кастомную условием
// нам сказали, что ссылку на другой контракт нельзя чисто, используем nns
func GetWinner(roomId string) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can get winner, room status must be voting
if !room.Host.Equals(getSender()) || room.Status != RoomStatusVoting {
return false
}
var round = room.Rounds[len(room.Rounds)-1]
if len(round.answers) == 0 {
panic(fmt.Sprintf("Round number %d does not have answers", len(room.Rounds)))
}
winner := round.answers[0]
// todo для mvp пока топ 1 победитель. потом сделаем CountWinners или кастомные реализации распределений
for _, answer := range round.answers {
if answer.votes > winner.votes {
winner = answer
}
}
for _, player := range room.Players {
sendMessageToPlayer(winner.answer, player)
}
// todo отправка награды
room.Status = RoomStatusGameIsStarted // Next game cycle available. to AskQuestion
storage.Put(ctx, []byte("room:"+roomId), room)
return true
}
func FinishGame(roomId string) bool {
var ctx = storage.GetContext()
var room = getRoom(ctx, roomId)
// Only host can finish game, room status must be game is going
if !room.Host.Equals(getSender()) || room.Status != RoomStatusGameIsStarted {
return false
}
// todo победитель всей игры? итоги? что нибудь еще?
room.Status = RoomStatusFinished
storage.Put(ctx, []byte("room:"+roomId), room)
return true
// todo добавить вилку, что если ВСЕ участники согласились закончить игру - заканчиваем
}
// todo логика выкидывания игрока из игры, если пропускает несколько вопросов подряд - делаем булевый флаг по которому определяем, активен игрок или нет

11
TestContract/neo-go.yml Normal file
View file

@ -0,0 +1,11 @@
name: TestContract
sourceurl: http://example.com/
safemethods: []
supportedstandards: []
events:
- name: Hello world!
parameters:
- name: args
type: Array
permissions:
- methods: '*'