<commit_before>/*
 * Copyright (c) 2016 Alex "ZeroKnight" George
 *
 * This file is licensed under the MIT License. For details, please see the
 * LICENSE file that should be included with the source code, or
 * <https://opensource.org/licenses/MIT>
 */

#include <sourcemod>

#pragma semicolon 1
#pragma newdecls required

char PLUGIN_NAME[]    = "Multi-Giveaway";
char PLUGIN_AUTHOR[]  = "Alex \"ZeroKnight\" George";
char PLUGIN_DESC[]    = "Expansive Giveaway system with numerous types of Giveaway events and stats";
char PLUGIN_VERSION[] = "0.2.0";
char PLUGIN_URL[]     = "http:/github.com/ZeroKnight/sm-Multi-Giveaway";
char PLUGIN_TAG[]     = "[MG]";

public Plugin myinfo =
{
  name        = PLUGIN_NAME,
  author      = PLUGIN_AUTHOR,
  description = PLUGIN_DESC,
  version     = PLUGIN_VERSION,
  url         = PLUGIN_URL
};

const int TYPEOPT_MAX_LEN = 64;

/* NOTE: (<<= 1) is actually a neat thing that SourcePawn does. It lets you
 * specify how to 'increment' each enumeration. In this case, each one will be
 * the previous value left shifted 1, which gives us our bit-field.
 */
enum GiveawayType (<<= 1)
{
  GT_Invalid = -1, GT_Dice = 1, GT_Number, GT_Kill, GT_All = 7
};
const int nGTypes = 3;

// Global state variables/data structures
StringMap GiveawayData;
ArrayList Dice_PlayerRolls;
ArrayList Dice_ReRolls;
ArrayList Number_PlayerGuesses;

ArrayList Current_TypeOpts; // NOTE: Subject to change

//File configfile = ...

// TODO: Put things like this in a personal core library?
#define CVAR(%1) ConVar cv_%1
char CVAR_PREFIX[] = "multi_giveaway";
CVAR(version);
CVAR(flags);
CVAR(enabled_types);
CVAR(player_state);
CVAR(min_conn_time);
CVAR(dice_min);
CVAR(dice_max);
CVAR(dice_show_rolls);
CVAR(dice_rerolls);
CVAR(number_min);
CVAR(number_max);
CVAR(number_show_guesses);

int abs(const int i) { return (i > 0) ? i : -i; }
int min(const int i, const int k) { return (i < k) ? i : k; }
int max(const int i, const int k) { return (i > k) ? i : k; }
int clamp(const int i, const int minval, const int maxval)
{
  return max(minval, min(i, maxval));
}

void RegisterConVars()
{
  // NOTE: Use HookConVarChange() for anything that needs it

  // XXX: Function overloads would be nice. Or casting that worked on strings.
  char sGT_All[32]; IntToString(view_as<int>(GT_All), sGT_All, sizeof(sGT_All));

  /* Core */
  cv_version = CreateConVar(
    "multi_giveaway_version",
    PLUGIN_VERSION,
    "Plugin version",
    FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
  cv_flags = CreateConVar(
    "multi_giveaway_flags",
    "b",
    "List of admin flags allowed to manage giveaways");
  cv_enabled_types = CreateConVar(
    "multi_giveaway_enabled_types",
    sGT_All,
    "Bit-field (sum of options) of enabled Giveaway types",
    FCVAR_NONE,
    true, 1.0,
    true, float(GT_All));
  cv_player_state = CreateConVar(
    "multi_giveaway_player_state",
    "2",
    "Player states eligible for Giveaway participation; each setting includes the previous one: 0 - Alive only, 1 - Dead, 2 - Spectator",
    FCVAR_NONE,
    true, 0.0,
    true, 2.0);
  cv_min_conn_time = CreateConVar( // TODO: Allow certain giveaways to override (eg. kill objective)
    "multi_giveaway_min_conn_time",
    "300", // 5 minutes
    "Amount of time in seconds a player must be connected to participate in a Giveaway",
    FCVAR_NONE,
    true, 0.0);

  /* Dice */
  cv_dice_min = CreateConVar(
    "multi_giveaway_dice_min",
    "1",
    "Lowest possible number a player may roll",
    FCVAR_NONE,
    true, 1.0);
  cv_dice_max = CreateConVar(
    "multi_giveaway_dice_max",
    "50",
    "Highest possible number a player may roll");
  cv_dice_show_rolls = CreateConVar(
    "multi_giveaway_dice_show_rolls",
    "0",
    "Who can see other clients' dice rolls: 0 - Nobody, 1 - Admins, 2 - Everyone",
    FCVAR_NONE,
    true, 0.0,
    true, 2.0);
  cv_dice_rerolls = CreateConVar(
    "multi_giveaway_dice_rerolls",
    "0",
    "Number of 'do-overs' a player gets when rolling. Only the last is counted, for better or for worse",
    FCVAR_NONE,
    true, 0.0);

  /* Number Guess */
  cv_number_min = CreateConVar(
    "multi_giveaway_number_min",
    "1",
    "Lower bound of the range of numbers",
    FCVAR_NONE,
    true, 1.0);
  cv_number_max = CreateConVar(
    "multi_giveaway_number_max",
    "100",
    "Upper bound of the range of numbers");
  cv_number_show_guesses = CreateConVar(
    "multi_giveaway_number_show_guesses",
    "2",
    "Who can see other clients' guesses: 0 - Nobody, 1 - Admins, 2 - Everyone",
    FCVAR_NONE,
    true, 0.0,
    true, 2.0);
}

void RegisterCommands()
{
  // XXX: Is there a better way to create aliases?
  // RegConsoleCmd for client commands (ie participation)
  // RegAdminCmd for admin commands (ie (start|stop)ing giveaways methodmap may
  // be helpful
  //
  // We can use AddCommandListener() to allow for "commands" that aren't
  // actually registered commands (think 'nominate')

  RegAdminCmd("sm_mg_reload", Command_ReloadConfig, ADMFLAG_CONFIG,
    "Reload configuration file");
  RegAdminCmd("sm_multigiveaway", Command_MultiGiveaway, ADMFLAG_GENERIC,
    "Manage giveaways");
  RegAdminCmd("sm_mg", Command_MultiGiveaway, ADMFLAG_GENERIC,
    "Manage giveaways");
  RegAdminCmd("sm_dice_rig", Command_Dice_Rig, ADMFLAG_CHEATS,
              "Rigs the Dice Giveaway so the chosen client wins");

  RegConsoleCmd("sm_rolldice", Command_Dice_Roll,
                "Rolls the dice during a Dice Giveaway");
  RegConsoleCmd("sm_reroll", Command_Dice_ReRoll,
                "Rolls the dice again during a Giveaway, giving you a new result (for better or worse!");
  RegConsoleCmd("sm_guess", Command_Number_Guess,
                "Guess a number for the Number-Guess Giveaway");
}

bool LoadConfig()
{
  //if (configfile != null) // is this boilerplate necessary?
    //CloseHandle(configfile);
  // ...
  return true;
}


void GetTypeName(const GiveawayType type, char[] str, int sz)
{
  switch (type)
  {
    case GT_Invalid: return;
    case GT_Dice:    strcopy(str, sz, "Dice");
    case GT_Number:  strcopy(str, sz, "Number");
    case GT_Kill:    strcopy(str, sz, "Kill");
    default:         return;
  }
}

GiveawayType GetType(const char[] typename)
{
  if      (StrEqual(typename, "dice", false))   return GT_Dice;
  else if (StrEqual(typename, "number", false)) return GT_Number;
  else if (StrEqual(typename, "kill", false))   return GT_Kill;
  else return GT_Invalid;
}

bool IsTypeEnabled(const GiveawayType type)
{
  return view_as<GiveawayType>(cv_enabled_types.IntValue) & type ? true : false;
}

GiveawayType GetCurrentGiveaway()<commit_msg>Missed a parameter that should have been const<commit_after>/*
 * Copyright (c) 2016 Alex "ZeroKnight" George
 *
 * This file is licensed under the MIT License. For details, please see the
 * LICENSE file that should be included with the source code, or
 * <https://opensource.org/licenses/MIT>
 */

#include <sourcemod>

#pragma semicolon 1
#pragma newdecls required

char PLUGIN_NAME[]    = "Multi-Giveaway";
char PLUGIN_AUTHOR[]  = "Alex \"ZeroKnight\" George";
char PLUGIN_DESC[]    = "Expansive Giveaway system with numerous types of Giveaway events and stats";
char PLUGIN_VERSION[] = "0.2.0";
char PLUGIN_URL[]     = "http:/github.com/ZeroKnight/sm-Multi-Giveaway";
char PLUGIN_TAG[]     = "[MG]";

public Plugin myinfo =
{
  name        = PLUGIN_NAME,
  author      = PLUGIN_AUTHOR,
  description = PLUGIN_DESC,
  version     = PLUGIN_VERSION,
  url         = PLUGIN_URL
};

const int TYPEOPT_MAX_LEN = 64;

/* NOTE: (<<= 1) is actually a neat thing that SourcePawn does. It lets you
 * specify how to 'increment' each enumeration. In this case, each one will be
 * the previous value left shifted 1, which gives us our bit-field.
 */
enum GiveawayType (<<= 1)
{
  GT_Invalid = -1, GT_Dice = 1, GT_Number, GT_Kill, GT_All = 7
};
const int nGTypes = 3;

// Global state variables/data structures
StringMap GiveawayData;
ArrayList Dice_PlayerRolls;
ArrayList Dice_ReRolls;
ArrayList Number_PlayerGuesses;

ArrayList Current_TypeOpts; // NOTE: Subject to change

//File configfile = ...

// TODO: Put things like this in a personal core library?
#define CVAR(%1) ConVar cv_%1
char CVAR_PREFIX[] = "multi_giveaway";
CVAR(version);
CVAR(flags);
CVAR(enabled_types);
CVAR(player_state);
CVAR(min_conn_time);
CVAR(dice_min);
CVAR(dice_max);
CVAR(dice_show_rolls);
CVAR(dice_rerolls);
CVAR(number_min);
CVAR(number_max);
CVAR(number_show_guesses);

int abs(const int i) { return (i > 0) ? i : -i; }
int min(const int i, const int k) { return (i < k) ? i : k; }
int max(const int i, const int k) { return (i > k) ? i : k; }
int clamp(const int i, const int minval, const int maxval)
{
  return max(minval, min(i, maxval));
}

void RegisterConVars()
{
  // NOTE: Use HookConVarChange() for anything that needs it

  // XXX: Function overloads would be nice. Or casting that worked on strings.
  char sGT_All[32]; IntToString(view_as<int>(GT_All), sGT_All, sizeof(sGT_All));

  /* Core */
  cv_version = CreateConVar(
    "multi_giveaway_version",
    PLUGIN_VERSION,
    "Plugin version",
    FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
  cv_flags = CreateConVar(
    "multi_giveaway_flags",
    "b",
    "List of admin flags allowed to manage giveaways");
  cv_enabled_types = CreateConVar(
    "multi_giveaway_enabled_types",
    sGT_All,
    "Bit-field (sum of options) of enabled Giveaway types",
    FCVAR_NONE,
    true, 1.0,
    true, float(GT_All));
  cv_player_state = CreateConVar(
    "multi_giveaway_player_state",
    "2",
    "Player states eligible for Giveaway participation; each setting includes the previous one: 0 - Alive only, 1 - Dead, 2 - Spectator",
    FCVAR_NONE,
    true, 0.0,
    true, 2.0);
  cv_min_conn_time = CreateConVar( // TODO: Allow certain giveaways to override (eg. kill objective)
    "multi_giveaway_min_conn_time",
    "300", // 5 minutes
    "Amount of time in seconds a player must be connected to participate in a Giveaway",
    FCVAR_NONE,
    true, 0.0);

  /* Dice */
  cv_dice_min = CreateConVar(
    "multi_giveaway_dice_min",
    "1",
    "Lowest possible number a player may roll",
    FCVAR_NONE,
    true, 1.0);
  cv_dice_max = CreateConVar(
    "multi_giveaway_dice_max",
    "50",
    "Highest possible number a player may roll");
  cv_dice_show_rolls = CreateConVar(
    "multi_giveaway_dice_show_rolls",
    "0",
    "Who can see other clients' dice rolls: 0 - Nobody, 1 - Admins, 2 - Everyone",
    FCVAR_NONE,
    true, 0.0,
    true, 2.0);
  cv_dice_rerolls = CreateConVar(
    "multi_giveaway_dice_rerolls",
    "0",
    "Number of 'do-overs' a player gets when rolling. Only the last is counted, for better or for worse",
    FCVAR_NONE,
    true, 0.0);

  /* Number Guess */
  cv_number_min = CreateConVar(
    "multi_giveaway_number_min",
    "1",
    "Lower bound of the range of numbers",
    FCVAR_NONE,
    true, 1.0);
  cv_number_max = CreateConVar(
    "multi_giveaway_number_max",
    "100",
    "Upper bound of the range of numbers");
  cv_number_show_guesses = CreateConVar(
    "multi_giveaway_number_show_guesses",
    "2",
    "Who can see other clients' guesses: 0 - Nobody, 1 - Admins, 2 - Everyone",
    FCVAR_NONE,
    true, 0.0,
    true, 2.0);
}

void RegisterCommands()
{
  // XXX: Is there a better way to create aliases?
  // RegConsoleCmd for client commands (ie participation)
  // RegAdminCmd for admin commands (ie (start|stop)ing giveaways methodmap may
  // be helpful
  //
  // We can use AddCommandListener() to allow for "commands" that aren't
  // actually registered commands (think 'nominate')

  RegAdminCmd("sm_mg_reload", Command_ReloadConfig, ADMFLAG_CONFIG,
    "Reload configuration file");
  RegAdminCmd("sm_multigiveaway", Command_MultiGiveaway, ADMFLAG_GENERIC,
    "Manage giveaways");
  RegAdminCmd("sm_mg", Command_MultiGiveaway, ADMFLAG_GENERIC,
    "Manage giveaways");
  RegAdminCmd("sm_dice_rig", Command_Dice_Rig, ADMFLAG_CHEATS,
              "Rigs the Dice Giveaway so the chosen client wins");

  RegConsoleCmd("sm_rolldice", Command_Dice_Roll,
                "Rolls the dice during a Dice Giveaway");
  RegConsoleCmd("sm_reroll", Command_Dice_ReRoll,
                "Rolls the dice again during a Giveaway, giving you a new result (for better or worse!");
  RegConsoleCmd("sm_guess", Command_Number_Guess,
                "Guess a number for the Number-Guess Giveaway");
}

bool LoadConfig()
{
  //if (configfile != null) // is this boilerplate necessary?
    //CloseHandle(configfile);
  // ...
  return true;
}


void GetTypeName(const GiveawayType type, char[] str, const int sz)
{
  switch (type)
  {
    case GT_Invalid: return;
    case GT_Dice:    strcopy(str, sz, "Dice");
    case GT_Number:  strcopy(str, sz, "Number");
    case GT_Kill:    strcopy(str, sz, "Kill");
    default:         return;
  }
}

GiveawayType GetType(const char[] typename)
{
  if      (StrEqual(typename, "dice", false))   return GT_Dice;
  else if (StrEqual(typename, "number", false)) return GT_Number;
  else if (StrEqual(typename, "kill", false))   return GT_Kill;
  else return GT_Invalid;
}

bool IsTypeEnabled(const GiveawayType type)
{
  return view_as<GiveawayType>(cv_enabled_types.IntValue) & type ? true : false;
}

GiveawayType GetCurrentGiveaway()
{'fraction_non_alphanumeric': 0.11045246492083739, 'fraction_numerical': 0.010204847302468673, 'mean_word_length': 3.707877075238432, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, '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': '6841104', 'n_tokens_mistral': 4736, 'n_tokens_neox': 4549, 'n_words': 1343}