<commit_before>/*
 * Copyright (C) 2012-2022  Online-Go.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* Usage:
 *
 * That data module is an interface that aids with storing local and remote
 * data. It is the underlying storage mechanism for the `preferences` system
 * which adds key name checking and ensures default values are set.
 *
 * The main methods are get, set, remove, setDefault, watch and unwatch
 *
 *   set(key, value, replication?)
 *       Sets the key value pair locally and optionally replicates the value to
 *       other devices used by the player. The replication parameter is
 *       described below.
 *
 *   remove(key, replication?)
 *       Removes the key value pair locally and optionally replicates the
 *       removal of the key to other devices used by the player. The
 *       replication parameter is described below.
 *
 *   setDefault(key, value)
 *       Sets a prioritized default value to be returned by get if no other
 *       value for the key is available, see get for more details on
 *       prioritization.
 *
 *   get(key, default_value?)
 *       This computes and returns the appropriate value for the given key.
 *       The value of a key can reside in several places. We check in order
 *       and return the first defined value we find.
 *
 *          If the value has been locally set (via set), that value is used.
 *          Else if the value has been set remotely, that value is used
 *          Else if the value has a default value set by setDefault, that value is used
 *          Else the default_value is returned, which may be undefined.
 *
 *   watch(key, cb: (value) => void, call_on_undefined?, dont_call_immediately?)
 *      When the value of a key (as determined by get(key) changes for any
 *      reason to some defined value, the callback is called with the new
 *      value. If you want the callback to be called even if the value is
 *      undefined, pass true for call_on_undefined. Normally, the callback
 *      is immediately called when you call watch to avoid having to duplicate
 *      a get and a watch statement, however if this behavior is not desired,
 *      pass true for the value of dont_call_immediately.
 *
 *   unwatch(key, cb: (value) => void)
 *      Removes a callback from being called when key is updated
 *
 *
 *   REPLICATION
 *
 *   The optional set and remove `replication` parameter can be set to one of
 *   the following values if replication to other devices used by the currently
 *   authenticated player is desired. (Note that if the user is not logged in,
 *   no replication will take place.)
 *
 *   values for replication:
 *
 *      Replication.NONE
 *          No replication is performed. This is the same as not passing this paramter.
 *
 *          When to use: When you don't want the value replicated to other devices
 *
 *
 *      Replication.LOCAL_OVERWRITES_REMOTE
 *          Replicate the value set/remove, however if the other device has already
 *          set the given value locally, use that value instead of the replicated value.
 *
 *          When to use: When you want to update an account wide default value, but
 *             not override any per-device defaults
 *
 *      Replication.REMOTE_OVERWRITES_LOCAL
 *          Replicate the value set/remove and overwrite the locally set values on
 *          other devices.
 *
 *          When to use: When you all devices and tabs to have the same value
 *
 *      Replication.REMOTE_ONLY
 *          Replicate the value set/remove but do not set/remove the local value
 *
 *          When to use: When you want to update the account wide default value, but
 *             not override any per-device defaults, including the current device
 *
 */

import { TypedEventEmitter } from "TypedEventEmitter";
import { DataSchema } from "data_schema";

export const events = new TypedEventEmitter<never>();

interface Events {
    [name: string]: any;
}

export enum Replication {
    NONE = 0x0, // No replication of this change
    LOCAL_OVERWRITES_REMOTE = 0x1, // Locally set data will overwrite remotely set data, but if not set will default to remotely set data
    REMOTE_OVERWRITES_LOCAL = 0x2, // Remotely set data will overwrite locally set data
    REMOTE_ONLY = 0x4, // Remotely set data, but do not update our local value
}

const defaults: Partial<DataSchema> = {};
const store: Partial<DataSchema> = {};

const event_emitter = new TypedEventEmitter<Events>();

//  Note that as well as "without emit", this is "without remote storage" as well.
// (you cant set-remote-storage-without-emit)
export function setWithoutEmit<KeyT extends Extract<keyof DataSchema, string>>(
    key: KeyT,
    value: DataSchema[KeyT] | undefined,
): DataSchema[KeyT] {
    if (value === undefined) {
        remove(key);
        return value;
    }

    store[key] = value;
    safeLocalStorageSet(`ogs.${key}`, JSON.stringify(value));<commit_msg>Tidy up typing of data events emitter<commit_after>/*
 * Copyright (C) 2012-2022  Online-Go.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* Usage:
 *
 * That data module is an interface that aids with storing local and remote
 * data. It is the underlying storage mechanism for the `preferences` system
 * which adds key name checking and ensures default values are set.
 *
 * The main methods are get, set, remove, setDefault, watch and unwatch
 *
 *   set(key, value, replication?)
 *       Sets the key value pair locally and optionally replicates the value to
 *       other devices used by the player. The replication parameter is
 *       described below.
 *
 *   remove(key, replication?)
 *       Removes the key value pair locally and optionally replicates the
 *       removal of the key to other devices used by the player. The
 *       replication parameter is described below.
 *
 *   setDefault(key, value)
 *       Sets a prioritized default value to be returned by get if no other
 *       value for the key is available, see get for more details on
 *       prioritization.
 *
 *   get(key, default_value?)
 *       This computes and returns the appropriate value for the given key.
 *       The value of a key can reside in several places. We check in order
 *       and return the first defined value we find.
 *
 *          If the value has been locally set (via set), that value is used.
 *          Else if the value has been set remotely, that value is used
 *          Else if the value has a default value set by setDefault, that value is used
 *          Else the default_value is returned, which may be undefined.
 *
 *   watch(key, cb: (value) => void, call_on_undefined?, dont_call_immediately?)
 *      When the value of a key (as determined by get(key) changes for any
 *      reason to some defined value, the callback is called with the new
 *      value. If you want the callback to be called even if the value is
 *      undefined, pass true for call_on_undefined. Normally, the callback
 *      is immediately called when you call watch to avoid having to duplicate
 *      a get and a watch statement, however if this behavior is not desired,
 *      pass true for the value of dont_call_immediately.
 *
 *   unwatch(key, cb: (value) => void)
 *      Removes a callback from being called when key is updated
 *
 *
 *   REPLICATION
 *
 *   The optional set and remove `replication` parameter can be set to one of
 *   the following values if replication to other devices used by the currently
 *   authenticated player is desired. (Note that if the user is not logged in,
 *   no replication will take place.)
 *
 *   values for replication:
 *
 *      Replication.NONE
 *          No replication is performed. This is the same as not passing this paramter.
 *
 *          When to use: When you don't want the value replicated to other devices
 *
 *
 *      Replication.LOCAL_OVERWRITES_REMOTE
 *          Replicate the value set/remove, however if the other device has already
 *          set the given value locally, use that value instead of the replicated value.
 *
 *          When to use: When you want to update an account wide default value, but
 *             not override any per-device defaults
 *
 *      Replication.REMOTE_OVERWRITES_LOCAL
 *          Replicate the value set/remove and overwrite the locally set values on
 *          other devices.
 *
 *          When to use: When you all devices and tabs to have the same value
 *
 *      Replication.REMOTE_ONLY
 *          Replicate the value set/remove but do not set/remove the local value
 *
 *          When to use: When you want to update the account wide default value, but
 *             not override any per-device defaults, including the current device
 *
 */

import { TypedEventEmitter } from "TypedEventEmitter";
import { DataSchema } from "data_schema";

interface DataEvents {
    remote_data_sync_complete: never;
}

export const events = new TypedEventEmitter<DataEvents>();

interface Events {
    [name: string]: any;
}

export enum Replication {
    NONE = 0x0, // No replication of this change
    LOCAL_OVERWRITES_REMOTE = 0x1, // Locally set data will overwrite remotely set data, but if not set will default to remotely set data
    REMOTE_OVERWRITES_LOCAL = 0x2, // Remotely set data will overwrite locally set data
    REMOTE_ONLY = 0x4, // Remotely set data, but do not update our local value
}

const defaults: Partial<DataSchema> = {};
const store: Partial<DataSchema> = {};

const event_emitter = new TypedEventEmitter<Events>();

//  Note that as well as "without emit", this is "without remote storage" as well.
// (you cant set-remote-storage-without-emit)
export function setWithoutEmit<KeyT extends Extract<keyof DataSchema, string>>(
    key: KeyT,
    value: DataSchema[KeyT] | undefined,
): DataSchema[KeyT] {
    if (value === undefined) {
        remove(key);
        return value;
    }

    store[key] = value;
    safeLocalStorageSet(`ogs.${key}`, JSON.stringify(value));
{'fraction_non_alphanumeric': 0.06494780979569989, 'fraction_numerical': 0.0030332768311178517, 'mean_word_length': 2.9978601997146934, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2830580', 'n_tokens_mistral': 3004, 'n_tokens_neox': 2874, 'n_words': 1453}