Re: Check if there 6 last records of same type without gaps

Поиск
Список
Период
Сортировка
От Sándor Daku
Тема Re: Check if there 6 last records of same type without gaps
Дата
Msg-id CAKyoTgYAOcxoGmveH4Q3-7b-cGd8+LupnuseprRarPQGx_b2pg@mail.gmail.com
обсуждение исходный текст
Ответ на Check if there 6 last records of same type without gaps  (Alexander Farber <alexander.farber@gmail.com>)
Ответы Re: Check if there 6 last records of same type without gaps  (Alexander Farber <alexander.farber@gmail.com>)
Список pgsql-general
On 6 September 2016 at 12:32, Alexander Farber <alexander.farber@gmail.com> wrote:
Good afternoon,

for a 2-player game I store moves in the following 9.5.4 table:

CREATE TYPE words_action AS ENUM ('play', 'skip', 'swap', 'resign');

CREATE TABLE words_moves (
        mid SERIAL PRIMARY KEY,
        action words_action NOT NULL,
        gid integer NOT NULL REFERENCES words_games ON DELETE CASCADE,
        uid integer NOT NULL REFERENCES words_users ON DELETE CASCADE,
        played timestamptz NOT NULL,
        tiles jsonb,
        score integer CHECK (score > 0)
);

ALTER TABLE words_games ADD CONSTRAINT words_mid_fk FOREIGN KEY (mid) REFERENCES words_moves;

And then I have a custom function for skipping a move (and inserting a 'skip' into the above table):

CREATE OR REPLACE FUNCTION words_skip_game(
        IN in_uid integer,
        IN in_gid integer,
        OUT out_gid integer)
        RETURNS integer AS
$func$
DECLARE
        _finished timestamptz;
        _score1   integer;
        _score2   integer;
        _uid2     integer;
BEGIN
        INSERT INTO words_moves (
                action,
                gid,
                uid,
                played
        ) VALUES (
                'skip',
                in_gid,
                in_uid,
                CURRENT_TIMESTAMP
        );

Could you please suggest a good way to check that the last 6 moves where 'skip', so that I can end the game when each player skipped her move 3 times in a row?

        IF /* there are 6 'skip's - how to do it please? */ THEN
                _finished = CURRENT_TIMESTAMP;
        END IF;

Below is the rest of my function, thank you for any ideas -

Regards
Alex

        UPDATE words_games SET
                finished = _finished,
                played1  = CURRENT_TIMESTAMP
        WHERE
                gid      = in_gid AND
                player1  = in_uid AND
                finished IS NULL AND
                -- and it is first player's turn
                (played1 IS NULL OR played1 < played2)
        RETURNING
                gid,
                score1,
                score2,
                player2
        INTO
                out_gid,
                _score1, -- my score
                _score2, -- her score
                _uid2;

        IF NOT FOUND THEN
                UPDATE words_games SET
                        finished = _finished,
                        played2  = CURRENT_TIMESTAMP
                WHERE
                        gid      = in_gid AND
                        player2  = in_uid AND
                        finished IS NULL AND
                        -- and it is second player's turn
                        (played2 IS NULL OR played2 < played1);
                RETURNING
                        gid,
                        score2,  -- swapped
                        score1,
                        player1
                INTO
                        out_gid,
                        _score1,  -- my score
                        _score2,  -- her score
                        _uid2;
        END IF;

        IF NOT FOUND THEN
                RAISE EXCEPTION 'Game % not found for user %', in_gid, in_uid;
        END IF;

        -- game over, update win/loss/draw stat for both players
        IF _finished IS NOT NULL THEN
                IF _score1 > _score2 THEN

                        UPDATE words_users SET
                                win = win + 1
                        WHERE uid = in_uid;

                        UPDATE words_users SET
                                loss = loss + 1
                        WHERE uid = _uid2;

                ELSIF _score1 < _score2 THEN

                        UPDATE words_users SET
                                loss = loss + 1
                        WHERE uid = in_uid;

                        UPDATE words_users SET
                                win = win + 1
                        WHERE uid = _uid2;
                ELSE
                        UPDATE words_users SET
                                draw = draw + 1
                        WHERE uid = in_uid OR uid = _uid2;
                END IF;
        END IF;
END
$func$ LANGUAGE plpgsql;

Get the last 6 record and 

1.  ... action='SKIP' as isskip ... then you can group on and count the skip moves. If there is 6 of them the game ends.

2.  ... sum(case when action='SKIP' then 1 else 0 end) ... If the result is 6 the game ends

Regards,
Sándor

В списке pgsql-general по дате отправления:

Предыдущее
От: Alexander Farber
Дата:
Сообщение: Check if there 6 last records of same type without gaps
Следующее
От: Alexander Farber
Дата:
Сообщение: Re: Check if there 6 last records of same type without gaps