package services import ( "context" "database/sql" "errors" "evening_detective/internal/models" "log" _ "github.com/mattn/go-sqlite3" ) type Repository struct { db *sql.DB } func NewRepository(filepath string) (*Repository, error) { db, err := sql.Open("sqlite3", filepath) if err != nil { return nil, err } log.Printf("load db from: %s", filepath) _, err = db.Exec("CREATE TABLE IF NOT EXISTS teams (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL CHECK(length(trim(name)) > 0), password TEXT);") if err != nil { return nil, err } _, err = db.Exec("CREATE TABLE IF NOT EXISTS actions (id INTEGER PRIMARY KEY AUTOINCREMENT, place TEXT, teamId INTEGER);") if err != nil { return nil, err } _, err = db.Exec("CREATE TABLE IF NOT EXISTS applications (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, teamId INTEGER, state TEXT);") if err != nil { return nil, err } _, err = db.Exec("CREATE TABLE IF NOT EXISTS games (id INTEGER PRIMARY KEY AUTOINCREMENT, state TEXT, startAt TIMESTAMP, endAt TIMESTAMP);") if err != nil { return nil, err } return &Repository{db: db}, nil } func (r *Repository) Close() { r.db.Close() } func (r *Repository) GetTeams(ctx context.Context) ([]*models.Team, error) { rows, err := r.db.Query("select id, name, password from teams") if err != nil { return nil, err } defer rows.Close() teams := []*models.Team{} for rows.Next() { item := &models.Team{} err := rows.Scan(&item.ID, &item.Name, &item.Password) if err != nil { return nil, err } teams = append(teams, item) } return teams, nil } func (r *Repository) AddTeams(ctx context.Context, teams []*models.Team) ([]*models.Team, error) { for _, team := range teams { result, err := r.db.Exec("insert into teams (name, password) values ($1, $2)", team.Name, team.Password) if err != nil { return nil, err } team.ID, err = result.LastInsertId() if err != nil { return nil, err } } return teams, nil } func (r *Repository) GetActions(ctx context.Context, teamId int64) ([]*models.Action, error) { rows, err := r.db.Query("select id, place from actions where teamId = $1", teamId) if err != nil { return nil, err } defer rows.Close() actions := []*models.Action{} for rows.Next() { item := &models.Action{} err := rows.Scan(&item.ID, &item.Place) if err != nil { return nil, err } actions = append(actions, item) } return actions, nil } func (r *Repository) AddActions(ctx context.Context, teamId int64, actions []*models.Action) error { for _, action := range actions { _, err := r.db.Exec("insert into actions (place, teamId) values ($1, $2)", action.Place, teamId) if err != nil { return err } } return nil } func (r *Repository) GetTeam(ctx context.Context, teamId any, password any) (*models.Team, error) { rows, err := r.db.Query("select id, name from teams where LOWER(name) = LOWER($1) and password = $2", teamId, password) if err != nil { return nil, err } defer rows.Close() teams := []*models.Team{} for rows.Next() { item := &models.Team{} err := rows.Scan(&item.ID, &item.Name) if err != nil { return nil, err } teams = append(teams, item) } if len(teams) != 1 { return nil, errors.New("bad result") } return teams[0], nil } func (r *Repository) AddApplications(ctx context.Context, actions []*models.Action) error { for _, action := range actions { for _, application := range action.Applications { _, err := r.db.Exec("insert into applications (name, teamId, state) values ($1, $2, $3)", application.Name, action.TeamID, application.State) if err != nil { return err } } } return nil } func (r *Repository) GetApplications(ctx context.Context, teamId int64, state string) ([]*models.Application, error) { rows, err := r.db.Query("select id, name from applications where teamId = $1 and state = $2", teamId, state) if err != nil { return nil, err } defer rows.Close() applications := []*models.Application{} for rows.Next() { item := &models.Application{} err := rows.Scan(&item.ID, &item.Name) if err != nil { return nil, err } applications = append(applications, item) } return applications, nil } func (r *Repository) GiveApplications(ctx context.Context, teamId int64, applications []*models.Application) error { for _, application := range applications { _, err := r.db.Exec("update applications set state = \"gave\" where teamId = $1 and id = $2", teamId, application.ID) if err != nil { return err } } return nil } func (r *Repository) GetGame(ctx context.Context) (string, error) { rows, err := r.db.Query("select state from games limit 1") if err != nil { return "", err } defer rows.Close() state := "" if rows.Next() { err := rows.Scan(&state) if err != nil { return "", err } return state, nil } state = "NEW" _, err = r.db.Exec("insert into games (state) values ($1)", state) if err != nil { return "", err } return state, nil } func (r *Repository) GameUpdateState(ctx context.Context, state string) error { _, err := r.db.Exec("update games set state = $1", state) return err } func (r *Repository) DeleteAllTeams(ctx context.Context) error { _, err := r.db.Exec("delete from teams where 1") return err }