Основная структура
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { Joke, JokeSettings } from "./joke";
|
||||
|
||||
/**
|
||||
* Блок обработки перво-апрельских шуток
|
||||
*
|
||||
* @author Kozhilya
|
||||
*/
|
||||
export class AprilFoolsJokeClass {
|
||||
/**
|
||||
* Добавление шутки
|
||||
*
|
||||
* @param joke
|
||||
*/
|
||||
add(joke: Joke): void {
|
||||
this.jokes[joke.id] = joke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись новых настроек
|
||||
*
|
||||
* @param settings
|
||||
*/
|
||||
setSettings(settings: SettingsMap): void {
|
||||
for (const entry of Object.entries(settings)) {
|
||||
const id = entry[0];
|
||||
const jokeSettings = entry[1];
|
||||
|
||||
this.jokes[id].settings = { ...this.jokes[id].settings, ...jokeSettings };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка вероятности
|
||||
*
|
||||
* @param {number} chance Вероятность срабатывания
|
||||
* @returns {boolean} Флаг срабатывания (true - сработало)
|
||||
*/
|
||||
check(chance: number): boolean {
|
||||
return Math.random() < 0.01 * chance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Запуск шутки
|
||||
*
|
||||
* @param id
|
||||
* @param {boolean} forced
|
||||
*/
|
||||
start(id: string, forced: boolean = false) {
|
||||
if (!(id in this.jokes))
|
||||
return;
|
||||
|
||||
const joke = this.jokes[id];
|
||||
|
||||
if (!forced && !this.check(joke.settings.chance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
joke.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Запуск всех шуток
|
||||
*/
|
||||
startAll() {
|
||||
for (const key of Object.keys(this.jokes)) {
|
||||
this.start(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Перечисление всех шуток
|
||||
*/
|
||||
jokes: JokeMap = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Объект хранения шуток
|
||||
*/
|
||||
interface JokeMap {
|
||||
[key: string]: Joke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Объект задания настроек
|
||||
*/
|
||||
interface SettingsMap {
|
||||
[key: string]: JokeSettings;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Объект настроек шутки
|
||||
*/
|
||||
export interface JokeSettings {
|
||||
/**
|
||||
* Вероятность срабатывания в процентах (0 для отключения)
|
||||
*/
|
||||
chance: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Объект, описывающий шутку
|
||||
*/
|
||||
export abstract class Joke {
|
||||
/**
|
||||
* Идентификатор шутки
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Настройки шутки
|
||||
*/
|
||||
settings: JokeSettings;
|
||||
|
||||
/**
|
||||
* Флаг, указывающий, должна ли шутка быть запущена
|
||||
*/
|
||||
enabled: boolean;
|
||||
|
||||
/**
|
||||
* Флаг, указывающий, может ли шутка быть остановлена
|
||||
*/
|
||||
is_stopable: boolean;
|
||||
|
||||
/**
|
||||
* Запуск шутки
|
||||
*/
|
||||
abstract start(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Объект, описывающий шутку, которая может быть остановлена
|
||||
*/
|
||||
export abstract class StopableJoke extends Joke
|
||||
{
|
||||
/**
|
||||
* Остановка шутки, если возможно
|
||||
*/
|
||||
abstract stop(): void;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import { Joke, JokeSettings, StopableJoke } from "../joke";
|
||||
|
||||
/**
|
||||
* Форумо-трясение
|
||||
*
|
||||
* Страница форума начинает трястись
|
||||
*
|
||||
* @author Kozhilya
|
||||
*/
|
||||
export class ShakeJoke extends StopableJoke {
|
||||
|
||||
settings: ShakeJokeSettings;
|
||||
|
||||
private interval_id: NodeJS.Timer;
|
||||
|
||||
private items: JQuery;
|
||||
|
||||
private data_name: string = 'april-fools-shake';
|
||||
|
||||
|
||||
rand(a: number): number {
|
||||
return a + this.settings.force * (Math.random() * 2 - 1);
|
||||
}
|
||||
|
||||
start(): void {
|
||||
this.items = $(this.settings.selector);
|
||||
|
||||
this.items.each((_, elem) => {
|
||||
let data: ShakeJokeMargin = {};
|
||||
|
||||
this.settings.directions.forEach(d => {
|
||||
data[d] = parseInt($(elem).css('margin-' + d));
|
||||
});
|
||||
|
||||
$(elem).data(this.data_name, data);
|
||||
});
|
||||
|
||||
this.interval_id = setInterval(() => {
|
||||
this.items.each((_, elem) => {
|
||||
const data: ShakeJokeMargin = $(elem).data(this.data_name);
|
||||
|
||||
for (const entry of Object.entries(data)) {
|
||||
$(elem).css('margin-' + entry[0], this.rand(entry[1]))
|
||||
}
|
||||
});
|
||||
}, this.settings.interval);
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
clearInterval(this.interval_id);
|
||||
|
||||
this.items.each((_, elem) => {
|
||||
let data: ShakeJokeMargin = {};
|
||||
|
||||
this.settings.directions.forEach(d => {
|
||||
$(elem).css('margin-' + d, data[d]);
|
||||
});
|
||||
|
||||
$(elem).data(this.data_name, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ShakeJokeSettings implements JokeSettings {
|
||||
chance: number = 1;
|
||||
|
||||
/**
|
||||
* Направление тряски
|
||||
*/
|
||||
directions: string[] = ['top', 'left', 'bottom', 'left'];
|
||||
|
||||
/**
|
||||
* Селектор всех элементов, которые будут трястись
|
||||
*/
|
||||
selector: string = '[id^=pun]';
|
||||
|
||||
/**
|
||||
* Частота тряски
|
||||
*/
|
||||
interval: number = 100;
|
||||
|
||||
/**
|
||||
* Сила тряски
|
||||
*/
|
||||
force: number = 0.5;
|
||||
}
|
||||
|
||||
interface ShakeJokeMargin {
|
||||
[key: string]: number;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { AprilFoolsJokeClass } from "./handler";
|
||||
import { Joke } from "./joke";
|
||||
import { ShakeJoke } from "./jokes/shake";
|
||||
|
||||
(window as any).AprilJokes = ((jokes: JokeClassList): AprilFoolsJokeClass => {
|
||||
const cl = new AprilFoolsJokeClass();
|
||||
|
||||
jokes.forEach(joke => {
|
||||
cl.add(new joke());
|
||||
});
|
||||
|
||||
return cl;
|
||||
})([
|
||||
ShakeJoke,
|
||||
]);
|
||||
|
||||
interface JokeClassList extends Array<new () => Joke> {}
|
||||
Reference in New Issue
Block a user