Php-да ұзақ уақыт бойы жұмыс істейтін ғаламдық таймер

Менің өтінімімде бірнеше нақты емес «ойындар» бар. Әр ойында әр ойыншыға ұпай беріледі. Ойын барысында ойыншылар кез-келген әрекетті орындау кезегін алады.

Дегенмен, егер талап етілмейтін уақыт ішінде ешқандай әрекет жасалмаса (кез келген жерде 1 сағаттан 1 айға дейін), онда екі ойыншы ұпай саны x жоғалтады.

Менің ойымша, жаһандық «таймер» деп ойладым. 1 сағаттық интервалда таймер әрбір ойынның deductPoints() функциясын шақырады.

deductPoints() функциясы ішінде келесідей нәрсені жасаймын:

deductPoints()
{
   timeSinceLastDeduction++;
   if(timeSinceLastDeduction >= frequencyOfDeduction)
   {
       deduct();
       timeSinceLastDeduction = 0;
   }
}

Бұл тапсырманы орындаудың жақсы жолы бар ма?

3
Ия. Бұл әлі іске асырылған жоқ, бірақ менің қазіргі жобамда мемлекеттік деректердің дерекқорын мемлекеттік тұрақтылыққа қолдану туралы ойладым.
қосылды автор Razor Storm, көзі
Сіз бұл деректерді реляциялық деректер базасында сақтайсыз ба?
қосылды автор Conspicuous Compiler, көзі
Сіз бір әдісті шақыру үшін ықтимал көп нысандарды құруды қажет етпестен, ұпайларды жаңартудың әдісін бір сұрауда қарастырғыңыз келуі мүмкін.
қосылды автор Michael Mior, көзі

2 жауаптар

Кезек өзгергенде, ағымдағы уақыт белгісін дерекқорға сақтап қойыңыз, содан кейін белгілі бір аралықта тексеруді орындау үшін cron функциясын қолданыңыз және егер қажетті уақыт өткен болса, ойын функцияларын орындаңыз.

Негізінде сен сияқты көрінген сияқты, бірақ уақыттың мәндерін бір жерде сақтау керек. Дерекқорға немесе файлға.

1
қосылды
Салқын, бұл туралы барынша тиімді тәсілі бар ма деген сұрақ туындайды. Бұл схемада айтатынымдай, 1000 ойыным бар, яғни әр сағат сайын барлық 1000 ойынды «оятуға» тура келеді, тіпті егер олардың тек екеуі сағат сайын
қосылды автор Razor Storm, көзі
Егер 1000 ұқсас ойындарыңыз бар болса, сіз қандай ойындарды назар аударып, олардың функцияларын басқаратындығын тексеретін cron-дан бір сценарийді іске қосасыз.
қосылды автор budwiser, көзі

Қосымша деректерді сақтауға дайын болсаңыз, мен осы дизайнды ұсынар едім.

Кез келген уақытта ойынды шегерудің орнына (ойынның «күйіне» сүйеніп) орнына, ойыншылардың қабылдаған әрекетін сақтаңыз. Мысалы, осы кестені алуға мүмкіндік береді:

 id | playerid | action   |         stamp
----+----------+----------+------------------------
  1 |        1 | e2 to e4 | 2011-10-27 04:00:00-04
  2 |        1 |          | 2011-10-27 04:30:00-04
  3 |        1 |          | 2011-10-27 06:00:00-04
  4 |        1 |          | 2011-10-27 07:45:00-04
  5 |        1 |          | 2011-10-27 08:00:00-04

Және т.б.

e2 - e4 - шахмат қозғалысы, әдеттегі ашылудың бірі. Сіздің ойыңыз, мен оны жасай алмаймын. «Әрекет» қосымша болып табылады, алайда, сіз тек айыппұлды есептеу үшін әрекет болған фактіні сақтауыңыз қажет. (Бірақ, әрине, сізде кеңістік бар болғанша қосымша ақпаратты сақтауға болады).

«id» - осы жағдайда суррогат кілті. Postgresql-да DDL келесідей көрінеді:

CREATE TABLE actions(
  id BIGSERIAL PRIMARY KEY,
  playerid int,
  action text,
  stamp timestamptz,
  UNIQUE(playerid, stamp));

Тупле (playerid, мөртабан) «нақты» бастапқы кілт болады. «id» - суррогат кілті.

Уақыт белгілеріндегі айырмашылықты көру үшін, код терезе функцияларын қолдану арқылы қарапайым болып табылады. (PostgreSQL-ды пайдалануды жалғастыру)

select playerid, time_between, id FROM
        (SELECT playerid,
                stamp - lag(stamp) OVER() as time_between,
                id FROM actions
                ORDER BY stamp)
                as ss
        WHERE playerid = 1
                AND time_between > '1 hour';

Сынақ деректерін ертерек бергенде, үлгі нәтижесі:

 playerid | time_between | id
----------+--------------+----
        1 | 01:30:00     |  3
        1 | 01:45:00     |  4

Сізде cron тапсырмалары жоқ. Сіз қосымша деректерді сақтадыңыз (сондықтан әрекеттерді «жою» оңай болады). Ойыншыларыңыз қалаған болса, өткен қадамдарды қарап шығуы мүмкін. Егер айыппұлды есептеу тиімді болмаса, онда сіз әрқашан жоғары деңгейде баллды кэште аласыз.

Терезенің функциялары MySQL btw ішінде қол жетімді емес. Бірақ PostgreSQL, SQL Server және Oracle-те қол жетімді.

ӨҢДЕУ: Егер орын алаңдаушылық тудырса, онда бұл кестені үнемі «қоқыс жинау» мүмкін. Дегенмен, бұл көптеген ойындар. Әрбір жол 48 байтты құрайды (бос «әрекет» деп болжанған). Егер сізде 1000 ойыншы болса, олардың әрқайсысы 40 әрекеті бар 200 ойын ойнайтын болса, сізде тек қана ~ 384 Мб деректер бар.

1
қосылды
Өте керемет, терезе функцияларына бұрын кірмегеніме сенбеймін. Мен бұған қарап шығадым.
қосылды автор Razor Storm, көзі
Ия, менің mysql-ды қолдануға тура келеді, сондықтан оны негізінен қолданбалы кодта жасаймын. Рахмет!
қосылды автор Razor Storm, көзі
Егер сіз мұны MySQL немесе кез келген басқа дерекқормен терезе функцияларынсыз жасау керек болса, ойыншының осы ойыннан барлық әрекеттерін қайтару оңай болады. Содан кейін оны қолданбалы кодта есептейсіз. Деректерді талдауға арналған қолданба кодексінен ұялма. Осының бәрін SQL-де орындауға болатын таза амал, бірақ сізге қажет болмаса, оны орындауға назар аудармаңыз.
қосылды автор Dragontamer5788, көзі