text:
#include <stdio.h>
#include <float.h>
#include <sstream>
#include <fstream>

#include "cache.h"
#include "io_buf.h"
#include "parse_regressor.h"
#include "parser.h"
#include "parse_args.h"
#include "sender.h"
#include "network.h"
#include "global_data.h"
#include "nn.h"
#include "cbify.h"
#include "oaa.h"
#include "rand48.h"
#include "bs.h"
#include "topk.h"
#include "ect.h"
#include "csoaa.h"
#include "cb.h"
#include "cb_algs.h"
#include "scorer.h"
#include "search.h"
#include "bfgs.h"
#include "lda_core.h"
#include "noop.h"
#include "print.h"
#include "gd_mf.h"
#include "mf.h"
#include "vw.h"
#include "rand48.h"
#include "parse_args.h"
#include "binary.h"
#include "lrq.h"
#include "autolink.h"
#include "log_multi.h"
#include "memory.h"
#include "stagewise_poly.h"
#include "active.h"
#include "kernel_svm.h"
#include "parse_example.h"

using namespace std;
//
// Does string end with a certain substring?
//
bool ends_with(string const &fullString, string const &ending)
{
    if (fullString.length() > ending.length()) {
        return (fullString.compare(fullString.length() - ending.length(), ending.length(), ending) == 0);
    } else {
        return false;
    }
}

bool valid_ns(char c)
{
    if (c=='|'||c==':')
        return false;
    return true;
}

bool substring_equal(substring&a, substring&b) {
  return (a.end - a.begin == b.end - b.begin) // same length
      && (strncmp(a.begin, b.begin, a.end - a.begin) == 0);
}

void parse_dictionary_argument(vw&all, string str) {
  if (str.length() == 0) return;
  // expecting 'namespace:file', for instance 'w:foo.txt'
  // in the case of just 'foo.txt' it's applied to the default namespace

  char ns = ' ';
  const char*s  = str.c_str();
  if ((str.length() > 3) && (str[1] == ':')) {
    ns = str[0];
    s  += 2;
  }

  // see if we've already read this dictionary
  for (size_t id=0; id<all.read_dictionaries.size(); id++)
    if (strcmp(all.read_dictionaries[id].name, s) == 0) {
      all.namespace_dictionaries[(size_t)ns].push_back(all.read_dictionaries[id].dict);
      return;
    }

  feature_dict* map = new feature_dict(1023, NULL, substring_equal);

  // TODO: handle gzipped dictionaries
  example *ec = alloc_examples(all.p->lp.label_size, 1);
  ifstream infile(s);
  size_t def = (size_t)' ';
  for (string line; getline(infile, line);) {
    char*c = (char*)line.c_str(); // we're throwing away const, which is dangerous...
    while (*c == ' ' || *c == '\t') ++c; // skip initial whitespace
    char*d = c;
    while (*d != ' ' && *d != '\t' && *d != '\n' && *d != '\0') ++d; // gobble up initial word
    if (d == c) continue; // no word
    if (*d != ' ' && *d != '\t') continue; // reached end of line
    char*word = (char*)calloc(d-c, sizeof(char));
    memcpy(word, c, d-c);
    substring ss = { word, word + (d - c) };
    uint32_t hash = uniform_hash( ss.begin, ss.end-ss.begin, quadratic_constant);
    if (map->get(ss, hash) != NULL) { // don't overwrite old values!
      free(word);
      continue;
    }

    d--;
    *d = '|';  // set up for parser::read_line
    read_line(all, ec, d);
    // now we just need to grab stuff from the default namespace of ec!
    if (ec->atomics[def].size() == 0) {
      free(word);
      continue;
    }
    v_array<feature>* arr = new v_array<feature>();
    push_many(*arr, ec->atomics[def].begin, ec->atomics[def].size());
    map->put(ss, hash, arr);
  }
  dealloc_example(all.p->lp.delete_label, *ec);
  free(ec);

  cerr << "dictionary " << s << " contains " << map->size() << " item" << (map->size() == 1 ? "\n" : "s\n");
  all.namespace_dictionaries[(size_t)ns].push_back(map);
  dictionary_info info = { (char*)calloc(strlen(s)+1, sizeof(char)), map };
  strcpy(info.name, s);
  all.read_dictionaries.push_back(info);
}

void parse_affix_argument(vw&all, string str) {
  if (str.length() == 0) return;
  char* cstr = (char*)calloc_or_die(str.length()+1, sizeof(char));
  strcpy(cstr, str.c_str());

  char*p = strtok(cstr, ",");
  while (p != 0) {
    char*q = p;
    uint16_t prefix = 1;
    if (q[0] == '+') { q++; }
    else if (q[0] == '-') { prefix = 0; q++; }
    if ((q[0] < '1') || (q[0] > '7')) {
      cerr << "malformed affix argument (length must be 1..7): " << p << endl;
      throw exception();
    }
    uint16_t len = (uint16_t)(q[0] - '0');
    uint16_t ns = (uint16_t)' ';  // default namespace
    if (q[1] != 0) {
      if (valid_ns(q[1]))
        ns = (uint16_t)q[1];
      else {
        cerr << "malformed affix argument (invalid namespace): " << p << endl;
        throw exception();
      }
      if (q[2] != 0) {
        cerr << "malformed affix argument (too long): " << p << endl;
        throw exception();
      }
    }

    uint16_t afx = (len << 1) | (prefix & 0x1);
    all.affix_features[ns] <<= 4;
    all.affix_features[ns] |=  afx;

    p = strtok(NULL, ",");
  }

  free(cstr);
}

void parse_diagnostics(vw& all, po::variables_map& vm, int argc)
{
  po::options_description diag_opt("Diagnostic options");

  diag_opt.add_options()
    ("version","Version information")
    ("audit,a", "print weights of features")
    ("progress,P", po::value< string >(), "Progress update frequency. int: additive, float: multiplicative")
    ("quiet", "Don't output disgnostics and progress updates")
    ("help,h","Look here: http://hunch.net/~vw/ and click on Tutorial.");

  vm = add_options(all, diag_opt);

  if (vm.count("version")) {
    /* upon direct query for version -- spit it out to stdout */
    cout << version.to_string() << "\n";
    exit(0);
  }

  if (vm.count("quiet")) {
    all.quiet = true;
    // --quiet wins over --progress
  } else {
    if (argc == 1)
      cerr << "For more information use: vw --help" << endl;

    all.quiet = false;

    if (vm.count("progress")) {
      string progress_str = vm["progress"].as<string>();
      all.progress_arg = (float)::atof(progress_str.c_str());

      // --progress interval is dual: either integer or floating-point
      if (progress_str.find_first_of(".") == string::npos) {
        // No "." in arg: assume integer -> additive
        all.progress_add = true;
        if (all.progress_arg < 1) {
          cerr    << "warning: additive --progress <int>"
                  << " can't be < 1: forcing to 1\n";
          all.progress_arg = 1;

        }
        all.sd->dump_interval = all.progress_arg;

      } else {
        // A "." in arg: assume floating-point -> multiplicative
        all.progress_add = false;

        if (all.progress_arg <= 1.0) {
          cerr    << "warning: multiplicative --progress <float>: "
                  << vm["progress"].as<string>()
                  << " is <= 1.0: adding 1.0\n";
          all.progress_arg += 1.0;

        } else if (all.progress_arg > 9.0) {
          cerr    << "warning: multiplicative --progress <float>"
                  << " is > 9.0: you probably meant to use an integer\n";
        }
        all.sd->dump_interval = 1.0;
      }
    }
  }

  if (vm.count("audit")){
    all.audit = true;
  }
}

void parse_source(vw& all, po::variables_map& vm)
{
  po::options_description in_opt("Input options");

  in_opt.add_options()
    ("data,d", po::value< string >(), "Example Set")
    ("daemon", "persistent daemon mode on port 26542")
    ("port", po::value<size_t>(),"port to listen on; use 0 to pick unused port")
    ("num_children", po::value<size_t>(&(all.num_children)), "number of children for persistent daemon mode")
    ("pid_file", po::value< string >(), "Write pid file in persistent daemon mode")
    ("port_file", po::value< string >(), "Write port used in persistent daemon mode")
    ("cache,c", "Use a cache.  The default is <data>.cache")
    ("cache_file", po::value< vector<string> >(), "The location(s) of cache_file.")
    ("kill_cache,k", "do not reuse existing cache: create a new one always")
    ("compressed", "use gzip format whenever possible. If a cache file is being created, this option creates a compressed cache file. A mixture of raw-text & compressed inputs are supported with autodetection.")
    ("no_stdin", "do not default to reading from stdin");

  vm = add_options(all, in_opt);

  // Be friendly: if -d was left out, treat positional param as data file
  po::positional_options_description p;
  p.add("data", -1);

  vm = po::variables_map();
  po::parsed_options pos = po::command_line_parser(all.args).
    style(po::command_line_style::default_style ^ po::command_line_style::allow_guessing).
    options(all.opts).positional(p).run();
  vm = po::variables_map();
  po::store(pos, vm);

  //begin input source
  if (vm.count("no_stdin"))
    all.stdin_off = true;

  if ( (vm.count("total") || vm.count("node") || vm.count("unique_id")) && !(vm.count("total") && vm.count("node") && vm.count("unique_id")) )
    {
      cout << "you must specificy unique_id, total, and node if you specify any" << endl;
      throw exception();
    }

  if (vm.count("daemon") || vm.count("pid_file") || (vm.count("port") && !all.active) ) {
    all.daemon = true;

    // allow each child to process up to 1e5 connections
    all.numpasses = (size_t) 1e5;
  }

  if (vm.count("compressed"))
      set_compressed(all.p);

  if (vm.count("data")) {
    all.data_filename = vm["data"].as<string>();
    if (ends_with(all.data_filename, ".gz"))
      set_compressed(all.p);
  } else
    all.data_filename = "";

  if ((vm.count("cache") || vm.count("cache_file")) && vm.count("invert_hash"))
    {
      cout << "invert_hash is incompatible with a cache file.  Use it in single pass mode only." << endl;
      throw exception();
    }

  if(!all.holdout_set_off && (vm.count("output_feature_regularizer_binary") || vm.count("output_feature_regularizer_text")))
    {
      all.holdout_set_off = true;
      cerr<<"Making holdout_set_off=true since output regularizer specified\n";
    }
}

void parse_feature_tweaks(vw& all, po::variables_map& vm)
{
  po::options_description feature_opt("Feature options");
  feature_opt.add_options()
    ("hash", po::value< string > (), "how to hash the features. Available options: strings, all")
    ("ignore", po::value< vector<unsigned char> >(), "ignore namespaces beginning with character <arg>")
    ("keep", po::value< vector<unsigned char> >(), "keep namespaces beginning with character <arg>")
    ("bit_precision,b", po::value<size_t>(), "number of bits in the feature table")
    ("noconstant", "Don't add a constant feature")
    ("constant,C", po::value<float>(&(all.initial_constant)), "Set initial value of constant")
    ("ngram", po::value< vector<string> >(), "Generate N grams. To generate N grams for a single namespace 'foo', arg should be fN.")
    ("skips", po::value< vector<string> >(), "Generate skips in N grams. This in conjunction with the ngram tag can be used to generate generalized n-skip-k-gram. To generate n-skips for a single namespace 'foo', arg should be fN.")
    ("feature_limit", po::value< vector<string> >(), "limit to N features. To apply to a single namespace 'foo', arg should be fN")
    ("affix", po::value<string>(), "generate prefixes/suffixes of features; argument '+2a,-3b,+1' means generate 2-char prefixes for namespace a, 3-char suffixes for b and 1 char prefixes for default namespace")
    ("spelling", po::value< vector<string> >(), "compute spelling features for a give namespace (use '_' for default namespace)")
    ("dictionary", po::value< vector<string> >(), "read a dictionary for additional features (arg either 'x:file' or just 'file')")
    ("quadratic,q", po::value< vector<string> > (), "Create and use quadratic features")
    ("q:", po::value< string >(), ": corresponds to a wildcard for all printable characters")
    ("cubic", po::value< vector<string> > (),
     "Create and use cubic features");

  vm = add_options(all, feature_opt);

  //feature manipulation
  string hash_function("strings");
  if(vm.count("hash"))
    hash_function = vm["hash"].as<string>();
  all.p->hasher = getHasher(hash_function);

  if (vm.count("spelling")) {
    vector<string> spelling_ns = vm["spelling"].as< vector<string> >();
    for (size_t id=0; id<spelling_ns.size(); id++)
      if (spelling_ns[id][0] == '_') all.spelling_features[(unsigned char)' '] = true;
      else all.spelling_features[(size_t)spelling_ns[id][0]] = true;
  }

  if (vm.count("affix")) {
    parse_affix_argument(all, vm["affix"].as<string>());
    stringstream ss;
    ss << " --affix " << vm["affix"].as<string>();
    all.file_options.append(ss.str());
  }

  if(vm.count("ngram")){
    if(vm.count("sort_features"))
      {
	cerr << "ngram is incompatible with sort_features.  " << endl;
	throw exception();
      }

    all.ngram_strings = vm["ngram"].as< vector<string> >();
    compile_gram(all.ngram_strings, all.ngram, (char*)"grams", all.quiet);
  }

  if(vm.count("skips"))
    {
      if(!vm.count("ngram"))
	{
	  cout << "You can not skip unless ngram is > 1" << endl;
	  throw exception();
	}

      all.skip_strings = vm["skips"].as<vector<string> >();
      compile_gram(all.skip_strings, all.skips, (char*)"skips", all.quiet);
    }

  if(vm.count("feature_limit"))
    {
      all.limit_strings = vm["feature_limit"].as< vector<string> >();
      compile_limits(all.limit_strings, all.limit, all.quiet);
    }

  if (vm.count("bit_precision"))
    {
      uint32_t new_bits = (uint32_t)vm["bit_precision"].as< size_t>();
      if (all.default_bits == false && new_bits != all.num_bits)
	{
	  cout << "Number of bits is set to " << new_bits << " and " << all.num_bits << " by argument and model.  That does not work." << endl;
	  throw exception();
	}
      all.default_bits = false;
      all.num_bits = new_bits;
      if (all.num_bits > min(32, sizeof(size_t)*8 - 3))
	{
	  cout << "Only " << min(32, sizeof(size_t)*8 - 3) << " or fewer bits allowed.  If this is a serious limit, speak up." << endl;
	  throw exception();
	}
    }

  if (vm.count("quadratic"))
    {
      all.pairs = vm["quadratic"].as< vector<string> >();
      vector<string> newpairs;
      //string tmp;
      char printable_start = '!';
      char printable_end = '~';
      int valid_ns_size = printable_end - printable_start - 1; //will skip two characters

      if(!all.quiet)
        cerr<<"creating quadratic features for pairs: ";

      for (vector<string>::iterator i = all.pairs.begin(); i != all.pairs.end();i++){
        if(!all.quiet){
          cerr << *i << " ";
          if (i->length() > 2)
            cerr << endl << "warning, ignoring characters after the 2nd.\n";
          if (i->length() < 2) {
            cerr << endl << "error, quadratic features must involve two sets.\n";
            throw exception();
          }
        }
        //-q x:
        if((*i)[0]!=':'&&(*i)[1]==':'){
          newpairs.reserve(newpairs.size() + valid_ns_size);
          for (char j=printable_start; j<=printable_end; j++){
            if(valid_ns(j))
              newpairs.push_back(string(1,(*i)[0])+j);
          }
        }
        //-q :x
        else if((*i)[0]==':'&&(*i)[1]!=':'){
          newpairs.reserve(newpairs.size() + valid_ns_size);
          for (char j=printable_start; j<=printable_end; j++){
            if(valid_ns(j)){
	      stringstream ss;
	      ss << j << (*i)[1];
	      newpairs.push_back(ss.str());
	    }
          }
        }
        //-q ::
        else if((*i)[0]==':'&&(*i)[1]==':'){
	  cout << "in pair creation" << endl;
          newpairs.reserve(newpairs.size() + valid_ns_size*valid_ns_size);
	  stringstream ss;
	  ss << ' ' << ' ';
	  newpairs.push_back(ss.str());
          for (char j=printable_start; j<=printable_end; j++){
            if(valid_ns(j)){
              for (char k=printable_start; k<=printable_end; k++){
                if(valid_ns(k)){
		  stringstream ss;
                  ss << j << k;
                  newpairs.push_back(ss.str());
		}
              }
            }
          }
        }
        else{
          newpairs.push_back(string(*i));
        }
      }
      newpairs.swap(all.pairs);
      if(!all.quiet)
        cerr<<endl;
    }

  if (vm.count("cubic"))
    {
      all.triples = vm["cubic"].as< vector<string> >();
      if (!all.quiet)
	{
	  cerr << "creating cubic features for triples: ";
	  for (vector<string>::iterator i = all.triples.begin(); i != all.triples.end();i++) {
	    cerr << *i << " ";
	    if (i->length() > 3)
	      cerr << endl << "warning, ignoring characters after the 3rd.\n";
	    if (i->length() < 3) {
	      cerr << endl << "error, cubic features must involve three sets.\n";
	      throw exception();
	    }
	  }
	  cerr << endl;
	}
    }

  for (size_t i = 0; i < 256; i++)
    all.ignore[i] = false;
  all.ignore_some = false;

  if (vm.count("ignore"))
    {
      all.ignore_some = true;

      vector<unsigned char> ignore = vm["ignore"].as< vector<unsigned char> >();
      for (vector<unsigned char>::iterator i = ignore.begin(); i != ignore.end();i++)
	{
	  all.ignore[*i] = true;
	}
      if (!all.quiet)
	{
	  cerr << "ignoring namespaces beginning with: ";
	  for (vector<unsigned char>::iterator i = ignore.begin(); i != ignore.end();i++)
	    cerr << *i << " ";

	  cerr << endl;
	}
    }

  if (vm.count("keep"))
    {
      for (size_t i = 0; i < 256; i++)
        all.ignore[i] = true;

      all.ignore_some = true;

      vector<unsigned char> keep = vm["keep"].as< vector<unsigned char> >();
      for (vector<unsigned char>::iterator i = keep.begin(); i != keep.end();i++)
	{
	  all.ignore[*i] = false;
	}
      if (!all.quiet)
	{
	  cerr << "using namespaces beginning with: ";
	  for (vector<unsigned char>::iterator i = keep.begin(); i != keep.end();i++)
	    cerr << *i << " ";

	  cerr << endl;
	}
    }

  if (vm.count("dictionary")) {
    vector<string> dictionary_ns = vm["dictionary"].as< vector<string> >();
    for (size_t id=0; id<dictionary_ns.size(); id++)
      parse_dictionary_argument(all, dictionary_ns[id]);
  }

  if (vm.count("noconstant"))
    all.add_constant = false;
}

void parse_example_tweaks(vw& all, po::variables_map& vm)
{
  po::options_description example_opts("Example options");

  example_opts.add_options()
    ("testonly,t", "Ignore label information and just test")
    ("holdout_off", "no holdout data in multiple passes")
    ("holdout_period", po::value<uint32_t>(&(all.holdout_period)), "holdout period for test only, default 10")
    ("holdout_after", po::value<uint32_t>(&(all.holdout_after)), "holdout after n training examples, default off (disables holdout_period)")
    ("early_terminate", po::value<size_t>(), "Specify the number of passes tolerated when holdout loss doesn't decrease before early termination, default is 3")
    ("passes", po::value<size_t>(&(all.numpasses)),"Number of Training Passes")
    ("initial_pass_length", po::value<size_t>(&(all.pass_length)), "initial number of examples per pass")
    ("examples", po::value<size_t>(&(all.max_examples)), "number of examples to parse")
    ("min_prediction", po::value<float>(&(all.sd->min_label)), "Smallest prediction to output")
    ("max_prediction", po::value<float>(&(all.sd->max_label)), "Largest prediction to output")
    ("sort_features", "turn this on to disregard order in which features have been defined. This will lead to smaller cache sizes")
    ("loss_function", po::value<string>()->default_value("squared"), "Specify the loss function to be used, uses squared by default. Currently available ones are squared, classic, hinge, logistic and quantile.")
    ("quantile_tau", po::value<float>()->default_value(0.5), "Parameter \\tau associated with Quantile loss. Defaults to 0.5")
    ("l1", po::value<float>(&(all.l1_lambda)), "l_1 lambda")
    ("l2", po::value<float>(&(all.l2_lambda)), "l_2 lambda");

  vm = add_options(all, example_opts);

  if (vm.count("testonly") || all.eta == 0.)
    {
      if (!all.quiet)
	cerr << "only testing" << endl;
      all.training = false;
      if (all.lda > 0)
        all.eta = 0;
    }
  else
    all.training = true;

  if(all.numpasses > 1)
      all.holdout_set_off = false;

  if(vm.count("holdout_off"))
      all.holdout_set_off = true;

  if(vm.count("sort_features"))
    all.p->sort_features = true;

  if (vm.count("min_prediction"))
    all.sd->min_label = vm["min_prediction"].as<float>();
  if (vm.count("max_prediction"))
    all.sd->max_label = vm["max_prediction"].as<float>();
  if (vm.count("min_prediction") || vm.count("max_prediction") || vm.count("testonly"))
    all.set_minmax = noop_mm;

  string loss_function;
  if(vm.count("loss_function"))
    loss_function = vm["loss_function"].as<string>();
  else
    loss_function = "squaredloss";
  float loss_parameter = 0.0;
  if(vm.count("quantile_tau"))
    loss_parameter = vm["quantile_tau"].as<float>();

  all.loss = getLossFunction(&all, loss_function, (float)loss_parameter);

  if (all.l1_lambda < 0.) {
    cerr << "l1_lambda should be nonnegative: resetting from " << all.l1_lambda << " to 0" << endl;
    all.l1_lambda = 0.;
  }
  if (all.l2_lambda < 0.) {
    cerr << "l2_lambda should be nonnegative: resetting from " << all.l2_lambda << " to 0" << endl;
    all.l2_lambda = 0.;
  }
  all.reg_mode += (all.l1_lambda > 0.) ? 1 : 0;
  all.reg_mode += (all.l2_lambda > 0.) ? 2 : 0;
  if (!all.quiet)
    {
      if (all.reg_mode %2 && !vm.count("bfgs"))
	cerr << "using l1 regularization = " << all.l1_lambda << endl;
      if (all.reg_mode > 1)
	cerr << "using l2 regularization = " << all.l2_lambda << endl;
    }
}

void parse_output_preds(vw& all, po::variables_map& vm)
{
  po::options_description out_opt("Output options");

  out_opt.add_options()
    ("predictions,p", po::value< string >(), "File to output predictions to")
    ("raw_predictions,r", po::value< string >(), "File to output unnormalized predictions to")
    ;

  vm = add_options(all, out_opt);

  if (vm.count("predictions")) {
    if (!all.quiet)
      cerr << "predictions = " <<  vm["predictions"].as< string >() << endl;
    if (strcmp(vm["predictions"].as< string >().c_str(), "stdout") == 0)
      {
	all.final_prediction_sink.push_back((size_t) 1);//stdout
      }
    else
      {
	const char* fstr = (vm["predictions"].as< string >().c_str());
	int f;
#ifdef _WIN32
	_sopen_s(&f, fstr, _O_CREAT|_O_WRONLY|_O_BINARY|_O_TRUNC, _SH_DENYWR, _S_IREAD|_S_IWRITE);
#else
	f = open(fstr, O_CREAT|O_WRONLY|O_LARGEFILE|O_TRUNC,0666);
#endif
	if (f < 0)
	  cerr << "Error opening the predictions file: " << fstr << endl;
	all.final_prediction_sink.push_back((size_t) f);
      }
  }

  if (vm.count("raw_predictions")) {
    if (!all.quiet) {
      cerr << "raw predictions = " <<  vm["raw_predictions"].as< string >() << endl;
      if (vm.count("binary"))
        cerr << "Warning: --raw has no defined value when --binary specified, expect no output" << endl;
    }
    if (strcmp(vm["raw_predictions"].as< string >().c_str(), "stdout") == 0)
      all.raw_prediction = 1;//stdout
    else
	{
	  const char* t = vm["raw_predictions"].as< string >().c_str();
	  int f;
#ifdef _WIN32
	  _sopen_s(&f, t, _O_CREAT|_O_WRONLY|_O_BINARY|_O_TRUNC, _SH_DENYWR, _S_IREAD|_S_IWRITE);
#else
	  f = open(t, O_CREAT|O_WRONLY|O_LARGEFILE|O_TRUNC,0666);
#endif
	  all.raw_prediction = f;
	}
  }
}

void parse_output_model(vw& all, po::variables_map& vm)
{
  po::options_description output_model("Output model");

  output_model.add_options()
    ("final_regressor,f", po::value< string >(), "Final regressor")
    ("readable_model", po::value< string >(), "Output human-readable final regressor with numeric features")
    ("invert_hash", po::value< string >(), "Output human-readable final regressor with feature names.  Computationally expensive.")
    ("save_resume", "save extra state so learning can be resumed later with new data")
    ("save_per_pass", "Save the model after every pass over data")
    ("output_feature_regularizer_binary", po::value< string >(&(all.per_feature_regularizer_output)), "Per feature regularization output file")
    ("output_feature_regularizer_text", po::value< string >(&(all.per_feature_regularizer_text)), "Per feature regularization output file, in text");

  vm = add_options(all, output_model);

  if (vm.count("final_regressor")) {
    all.final_regressor_name = vm["final_regressor"].as<string>();
    if (!all.quiet)
      cerr << "final_regressor = " << vm["final_regressor"].as<string>() << endl;
  }
  else
    all.final_regressor_name = "";

  if (vm.count("readable_model"))
    all.text_regressor_name = vm["readable_model"].as<string>();

  if (vm.count("invert_hash")){
    all.inv_hash_regressor_name = vm["invert_hash"].as<string>();
    all.hash_inv = true;
  }

  if (vm.count("save_per_pass"))
    all.save_per_pass = true;

  if (vm.count("save_resume"))
    all.save_resume = true;
}

void parse_base_algorithm(vw& all, po::variables_map& vm)
{
  //base learning algorithm.
  po::options_description base_opt("base algorithms (these are exclusive)");

  base_opt.add_options()
    ("sgd", "use regular stochastic gradient descent update.")
    ("adaptive", "use adaptive, individual learning rates.")
    ("invariant", "use safe/importance aware updates.")
    ("normalized", "use per feature normalized updates")
    ("exact_adaptive_norm", "use current default invariant normalized adaptive update rule")
    ("bfgs", "use bfgs optimization")
    ("lda", po::value<uint32_t>(&(all.lda)), "Run lda with <int> topics")
    ("rank", po::value<uint32_t>(&(all.rank)), "rank for matrix factorization.")
    ("noop","do no learning")
    ("print","print examples")
    ("ksvm", "kernel svm")
    ("sendto", po::value< vector<string> >(), "send examples to <host>");

  vm = add_options(all, base_opt);

  if (vm.count("bfgs") || vm.count("conjugate_gradient"))
    all.l = BFGS::setup(all, vm);
  else if (vm.count("lda"))
    all.l = LDA::setup(all, vm);
  else if (vm.count("noop"))
    all.l = NOOP::setup(all);
  else if (vm.count("print"))
    all.l = PRINT::setup(all);
  else if (all.rank > 0)
    all.l = GDMF::setup(all, vm);
  else if (vm.count("sendto"))
    all.l = SENDER::setup(all, vm, all.pairs);
  else if (vm.count("ksvm")) {
    string loss_function = "hinge";
    float loss_parameter = 0.0;
    all.loss = getLossFunction(&all, loss_function, (float)loss_parameter);
    all.l = KSVM::setup(all, vm);
  }
  else
    {
      all.l = GD::setup(all, vm);
      all.scorer = all.l;
    }
}

void load_input_model(vw& all, po::variables_map& vm, io_buf& io_temp)
{
  // Need to see if we have to load feature mask first or second.
  // -i and -mask are from same file, load -i file first so mask can use it
  if (vm.count("feature_mask") && vm.count("initial_regressor")
      && vm["feature_mask"].as<string>() == vm["initial_regressor"].as< vector<string> >()[0]) {
    // load rest of regressor
    all.l->save_load(io_temp, true, false);
    io_temp.close_file();

    // set the mask, which will reuse -i file we just loaded
    parse_mask_regressor_args(all, vm);
  }
  else {
    // load mask first
    parse_mask_regressor_args(all, vm);

    // load rest of regressor
    all.l->save_load(io_temp, true, false);
    io_temp.close_file();
  }
}

void parse_scorer_reductions(vw& all, po::variables_map& vm)
{
  po::options_description score_mod_opt("Score modifying options (can be combined)");

  score_mod_opt.add_options()
    ("nn", po::value<size_t>(), "Use sigmoidal feedforward network with <k> hidden units")
    ("new_mf", po::value<size_t>(), "rank for reduction-based matrix factorization")
    ("autolink", po::value<size_t>(), "create link function with polynomial d")
    ("lrq", po::value<vector<string> > (), "use low rank quadratic features")
    ("lrqdropout", "use dropout training for low rank quadratic features")
    ("stage_poly", "use stagewise polynomial feature learning")
    ("active", "enable active learning");

  vm = add_options(all, score_mod_opt);

  if (vm.count("active"))
    all.l = ACTIVE::setup(all,vm);

  if(vm.count("nn"))
    all.l = NN::setup(all, vm);

  if (vm.count("new_mf"))
    all.l = MF::setup(all, vm);

  if(vm.count("autolink"))
    all.l = ALINK::setup(all, vm);

  if (vm.count("lrq"))
    all.l = LRQ::setup(all, vm);

  if (vm.count("stage_poly"))
    all.l = StagewisePoly::setup(all, vm);

  all.l = Scorer::setup(all, vm);
}

LEARNER::learner* exclusive_setup(vw& all, po::variables_map& vm, bool& score_consumer, LEARNER::learner* (*setup)(vw&, po::variables_map&))
{
  if (score_consumer) { cerr << "error: cannot specify multiple direct score consumers" << endl; throw exception(); }
  score_consumer = true;
  return setup(all, vm);
}

void parse_score_users(vw& all, po::variables_map& vm, bool& got_cs)
{
  po::options_description multiclass_opt("Score user options (these are exclusive)");
  multiclass_opt.add_options()
    ("top", po::value<size_t>(), "top k recommendation")
    ("binary", "report loss as binary classification on -1,1")
    ("oaa", po::value<size_t>(), "Use one-against-all multiclass learning with <k> labels")
    ("ect", po::value<size_t>(), "Use error correcting tournament with <k> labels")
    ("log_multi", po::value<size_t>(), "Use online tree for multiclass")
    ("csoaa", po::value<size_t>(), "Use one-against-all multiclass learning with <k> costs")
    ("csoaa_ldf", po::value<string>(), "Use one-against-all multiclass learning with label dependent features.  Specify singleline or multiline.")
    ("wap_ldf", po::value<string>(), "Use weighted all-pairs multiclass learning with label dependent features.  Specify singleline or multiline.")
    ;

  vm = add_options(all, multiclass_opt);
  bool score_consumer = false;

  if(vm.count("top"))
    all.l = exclusive_setup(all, vm, score_consumer, TOPK::setup);

  if (vm.count("binary"))
    all.l = exclusive_setup(all, vm, score_consumer, BINARY::setup);

  if (vm.count("oaa"))
    all.l = exclusive_setup(all, vm, score_consumer, OAA::setup);

  if (vm.count("ect"))
    all.l = exclusive_setup(all, vm, score_consumer, ECT::setup);

  if(vm.count("csoaa")) {
    all.l = exclusive_setup(all, vm, score_consumer, CSOAA::setup);
    all.cost_sensitive = all.l;
    got_cs = true;
  }

  if(vm.count("log_multi")){
    all.l = exclusive_setup(all, vm, score_consumer, LOG_MULTI::setup);
  }

  if(vm.count("csoaa_ldf") || vm.count("csoaa_ldf")) {
    all.l = exclusive_setup(all, vm, score_consumer, CSOAA_AND_WAP_LDF::setup);
    all.cost_sensitive = all.l;
    got_cs = true;
  }

  if(vm.count("wap_ldf") || vm.count("wap_ldf") ) {
    all.l = exclusive_setup(all, vm, score_consumer, CSOAA_AND_WAP_LDF::setup);
    all.cost_sensitive = all.l;
    got_cs = true;
  }
}

void parse_cb(vw& all, po::variables_map& vm, bool& got_cs, bool& got_cb)
{
  po::options_description cb_opts("Contextual Bandit options");

  cb_opts.add_options()
    ("cb", po::value<size_t>(), "Use contextual bandit learning with <k> costs")
    ("cbify", po::value<size_t>(), "Convert multiclass on <k> classes into a contextual bandit problem and solve");

  vm = add_options(all,cb_opts);

  if( vm.count("cb"))
    {
      if(!got_cs) {
	if( vm.count("cb") ) vm.insert(pair<string,po::variable_value>(string("csoaa"),vm["cb"]));
	else vm.insert(pair<string,po::variable_value>(string("csoaa"),vm["cb"]));

	all.l = CSOAA::setup(all, vm);  // default to CSOAA unless wap is specified
	all.cost_sensitive = all.l;
	got_cs = true;
      }

      all.l = CB_ALGS::setup(all, vm);
      got_cb = true;
    }

  if (vm.count("cbify"))
    {
      if(!got_cs) {
	vm.insert(pair<string,po::variable_value>(string("csoaa"),vm["cbify"]));

	all.l = CSOAA::setup(all, vm);  // default to CSOAA unless wap is specified
	all.cost_sensitive = all.l;
	got_cs = true;
      }

      if (!got_cb) {
	vm.insert(pair<string,po::variable_value>(string("cb"),vm["cbify"]));
	all.l = CB_ALGS::setup(all, vm);
	got_cb = true;
      }

      all.l = CBIFY::setup(all, vm);
    }
}

void parse_search(vw& all, po::variables_map& vm, bool& got_cs, bool& got_cb)
{
  po::options_description search_opts("Search");

  search_opts.add_options()
      ("search",  po::value<size_t>(), "use search-based structured prediction, argument=maximum action id or 0 for LDF");

  vm = add_options(all,search_opts);

  if (vm.count("search")) {
    if (!got_cs && !got_cb) {
      if( vm.count("search") ) vm.insert(pair<string,po::variable_value>(string("csoaa"),vm["search"]));
      else vm.insert(pair<string,po::variable_value>(string("csoaa"),vm["search"]));

      all.l = CSOAA::setup(all, vm);  // default to CSOAA unless others have been specified
      all.cost_sensitive = all.l;
      got_cs = true;
    }
    all.l = Search::setup(all, vm);
  }
}

void add_to_args(vw& all, int argc, char* argv[])
{
  for (int i = 1; i < argc; i++)
    all.args.push_back(string(argv[i]));
}

vw* parse_args(int argc, char *argv[])
{
  vw* all = new vw();

  add_to_args(*all, argc, argv);

  size_t random_seed = 0;
  all->program_name = argv[0];

  po::options_description desc("VW options");

  desc.add_options()
    ("random_seed", po::value<size_t>(&random_seed), "seed random number generator")
    ("ring_size", po::value<size_t>(&(all->p->ring_size)), "size of example ring");

  po::options_description update_opt("Update options");

  update_opt.add_options()
    ("learning_rate,l", po::value<float>(&(all->eta)), "Set learning rate")
    ("power_t", po::value<float>(&(all->power_t)), "t power value")
    ("decay_learning_rate",    po::value<float>(&(all->eta_decay_rate)),
     "Set Decay factor for learning_rate between passes")
    ("initial_t", po::value<double>(&((all->sd->t))), "initial t value")
    ("feature_mask", po::value< string >(), "Use existing regressor to determine which parameters may be updated.  If no initial_regressor given, also used for initial weights.")
    ;

  po::options_description weight_opt("Weight options");

  weight_opt.add_options()
    ("initial_regressor,i", po::value< vector<string> >(), "Initial regressor(s)")
    ("initial_weight", po::value<float>(&(all->initial_weight)), "Set all weights to an initial value of 1.")
    ("random_weights", po::value<bool>(&(all->random_weights)), "make initial weights random")
    ("input_feature_regularizer", po::value< string >(&(all->per_feature_regularizer_input)), "Per feature regularization input file")
    ;

  po::options_description cluster_opt("Parallelization options");
  cluster_opt.add_options()
    ("span_server", po::value<string>(&(all->span_server)), "Location of server for setting up spanning tree")
    ("unique_id", po::value<size_t>(&(all->unique_id)),"unique id used for cluster parallel jobs")
    ("total", po::value<size_t>(&(all->total)),"total number of nodes used in cluster parallel job")
    ("node", po::value<size_t>(&(all->node)),"node number in cluster parallel job")
    ;

  po::options_description other_opt("Other options");
  other_opt.add_options()
    ("bootstrap,B", po::value<size_t>(), "bootstrap mode with k rounds by online importance resampling")
    ;

  desc.add(update_opt)
    .add(weight_opt)
    .add(cluster_opt)
    .add(other_opt);

  po::variables_map vm = add_options(*all, desc);

  msrand48(random_seed);

  parse_diagnostics(*all, vm, argc);

  all->sd->weighted_unlabeled_examples = all->sd->t;
  all->initial_t = (float)all->sd->t;

  //Input regressor header
  io_buf io_temp;
  parse_regressor_args(*all, vm, io_temp);

  int temp_argc = 0;
  char** temp_argv = VW::get_argv_from_string(all->file_options, temp_argc);
  add_to_args(*all, temp_argc, temp_argv);
  for (int i = 0; i < temp_argc; i++)
    free(temp_argv[i]);
  free(temp_argv);

  po::parsed_options pos = po::command_line_parser(all->args).
    style(po::command_line_style::default_style ^ po::command_line_style::allow_guessing).
    options(all->opts).allow_unregistered().run();

  vm = po::variables_map();

  po::store(pos, vm);
  po::notify(vm);
  all->file_options = "";

  parse_feature_tweaks(*all, vm); //feature tweaks

  parse_example_tweaks(*all, vm); //example manipulation

  parse_output_model(*all, vm);

  parse_base_algorithm(*all, vm);

  if (!all->quiet)
    {
      cerr << "Num weight bits = " << all->num_bits << endl;
      cerr << "learning rate = " << all->eta << endl;
      cerr << "initial_t = " << all->sd->t << endl;
      cerr << "power_t = " << all->power_t << endl;
      if (all->numpasses > 1)
	cerr << "decay_learning_rate = " << all->eta_decay_rate << endl;
      if (all->rank > 0)
	cerr << "rank = " << all->rank << endl;
    }

  parse_output_preds(*all, vm);

  parse_scorer_reductions(*all, vm);

  bool got_cs = false;

  parse_score_users(*all, vm, got_cs);

  bool got_cb = false;

  parse_cb(*all, vm, got_cs, got_cb);

  parse_search(*all, vm, got_cs, got_cb);

  if(vm.count("bootstrap"))
    all->l = BS::setup(*all, vm);

  load_input_model(*all, vm, io_temp);

  parse_source(*all, vm);

  enable_sources(*all, vm, all->quiet,all->numpasses);

  // force wpp to be a power of 2 to avoid 32-bit overflow
  uint32_t i = 0;
  size_t params_per_problem = all->l->increment;
  while (params_per_problem > (uint32_t)(1 << i))
    i++;
  all->wpp = (1 << i) >> all->reg.stride_shift;

  if (vm.count("help")) {
    /* upon direct query for help -- spit it out to stdout */
    cout << "\n" << all->opts << "\n";
    exit(0);
  }

  return all;
}

namespace VW {
  void cmd_string_replace_value( string& cmd, string flag_to_replace, string new_value )
  {
    flag_to_replace.append(" "); //add a space to make sure we obtain the right flag in case 2 flags start with the same set of characters
    size_t pos = cmd.find(flag_to_replace);
    if( pos == string::npos ) {
      //flag currently not present in command string, so just append it to command string
      cmd.append(" ");
      cmd.append(flag_to_replace);
      cmd.append(new_value);
    }
    else {
      //flag is present, need to replace old value with new value

      //compute position after flag_to_replace
      pos += flag_to_replace.size();

      //now pos is position where value starts
      //find position of next space
      size_t pos_after_value = cmd.find(" ",pos);
      if(pos_after_value == string::npos) {
        //we reach the end of the string, so replace the all characters after pos by new_value
        cmd.replace(pos,cmd.size()-pos,new_value);
      }
      else {
        //replace characters between pos and pos_after_value by new_value
        cmd.replace(pos,pos_after_value-pos,new_value);
      }
    }
  }

  char** get_argv_from_string(string s, int& argc)
  {
    char* c = (char*)calloc_or_die(s.length()+3, sizeof(char));
    c[0] = 'b';
    c[1] = ' ';
    strcpy(c+2, s.c_str());
    substring ss = {c, c+s.length()+2};
    v_array<substring> foo;
    foo.end_array = foo.begin = foo.end = NULL;
    tokenize(' ', ss, foo);

    char** argv = (char**)calloc_or_die(foo.size(), sizeof(char*));
    for (size_t i = 0; i < foo.size(); i++)
      {
	*(foo[i].end) = '\0';
	argv[i] = (char*)calloc_or_die(foo[i].end-foo[i].begin+1, sizeof(char));
        sprintf(argv[i],"%s",foo[i].begin);
      }

    argc = (int)foo.size();
    free(c);
    foo.delete_v();
    return argv;
  }

  vw* initialize(string s)
  {
    int argc = 0;
    s += " --no_stdin";
    char** argv = get_argv_from_string(s,argc);

    vw* all = parse_args(argc, argv);

    initialize_parser_datastructures(*all);

    for(int i = 0; i < argc; i++)
      free(argv[i]);
    free (argv);

    return all;
  }

  void delete_dictionary_entry(substring ss, v_array<feature>*A) {
    free(ss.begin);
    A->delete_v();
    delete A;
  }

  void finish(vw& all, bool delete_all)
  {
    finalize_regressor(all, all.final_regressor_name);
    all.l->finish();
    delete all.l;
    if (all.reg.weight_vector != NULL)
      free(all.reg.weight_vector);
    free_parser(all);
    finalize_source(all.p);
    all.p->parse_name.erase();
    all.p->parse_name.delete_v();
    free(all.p);
    free(all.sd);
    for (size_t i = 0; i < all.final_prediction_sink.size(); i++)
      if (all.final_prediction_sink[i] != 1)
	io_buf::close_file_or_socket(all.final_prediction_sink[i]);
    all.final_prediction_sink.delete_v();
    for (size_t i=0; i<256; i++) all.namespace_dictionaries[i].delete_v();
    for (size_t i=0; i<all.read_dictionaries.size(); i++) {
      free(all.read_dictionaries[i].name);
      all.read_dictionaries[i].dict->iter(delete_dictionary_entry);
      all.read_dictionaries[i].dict->delete_v();
      delete all.read_dictionaries[i].dict;
    }
    all.read_dictionaries.delete_v();
    delete all.loss;
    if (delete_all) delete &all;
  }
}

redpajama_set_name: RedPajamaGithub


text:
Q: Apache Solr Delete Query 3.6.2 Everytime i run a delete query in Apache Solr
i.e http://localhost:8983/solr/update?stream.body=<delete><query>id:APP 5.6.2*</query></delete>&commit=true

  <response> <lst name="responseHeader"><int name="status">0</int><int name="QTime">61</int></lst></response>

I get the above response and when i query my index to see if the document with that id has been deleted and it would still be able to query the doc that i deleted.
I am wondering what is the surest way to know that a document has been deleted from a solr index ? How long does it take see if it got deleted ?
I don't trust the Solr Reponse as surest way of knowing the delete query did what it was meant to do.

A: Figured out the answer to the Qn, i posted "id:APP 5.6.2*"
Solr does not interpret blank space so you need to escape them so when i did id:APP\ 5.6.2* it worked.
Also the Response xml you get is no practical indication of the success of the query.
It just means that the HTTP request has been received and in response you get the xml that i posted in the qn.
What happened was when i gave id:APP 5.6.2* => this got interpreted as id:APP and it did not find a document with id as APP so the document that you want to be deleted didnt get deleted.
so the query should be
http://localhost:8983/solr/update?stream.body=<delete><query>id:APP\ 5.6.2*</query></delete>&commit=true

A: You need to move the delete query parameter up in your Url. I suspect that it is getting lost after the query parameter. Try the following:
 http://localhost:8983/solr/update?commit=true&stream.body=<delete><query>id:APP 5.6.2*</query></delete>

redpajama_set_name: RedPajamaStackExchange


text:
Our Favourite Cheats, Mods, and/or ROM Hacks
by Doublejump August 4, 2020
Let's face it: we've all used them!
Some of us might prefer not to admit it, but we've all used a cheat code at some point in our gaming careers. Whether it's been to unlock everything for a casual session, to get our hands on stronger weapons or better vehicles, or just to clear our wanted level, there aren't too many situations we haven't been able to resolve with a cheeky cheat or two. Then there's the games we've played that we thought could be better with something changed, and the developers who put together a mod or a ROM Hack to make that exact change; we love those people, because it's through their work that we've had experiences we simply wouldn't have had otherwise.
In this latest Multiplayer entry, members of the Doublejump team sat down to take a look at those cheats, mods and ROM Hacks that have made their gaming experiences better over the years. Enjoy!
Abir: Counter-Strike: Source's Gun Game mode
[Credit: Sp00nerism on YouTube]
Gun Game was the right mode, at the right time, for the right game. While Xbox players were battling in Halo 3 and PlayStation fans were taking each other out in SOCOM, us PC gamers were bunny-hopping with knives in Counter-Strike (1.6) and Counter-Strike: Source. With its vibrant mod scene, CSS was a haven for hours of shenanigans, and Gun Game was a pearl among rocks. It was fast, frantic, and a great way to learn weapons that you might normally skip during regular matches.
For those of you who aren't familiar with GG, the mode sees all players spawn with the same starting weapon – usually a handgun – and earn more powerful weapons by fragging each other in a race to score the final kill using the venerable knife. Yes, it was stressful, but it was also a hell of a lot of fun! Other developers have aped Gun Game's basic premise for their own titles, yet none have captured the classic mode's frenetic atmosphere.
"You just had to be there, man."
Ben: Guitar Hero 3: Legends of Rock's cheats menu
Guitar Hero is the ultimate party game and I'm happy to accept any challenges to fight on that one. It's unique, it's interesting, and anyone can get in at the ground floor and have a good time with it. The third entry in the series is a little more forgiving on timing than the first two, something diehards at the time said was "too casual", but I think boosts its party credentials. It also had the best tracklist, with the budget from Guitar Hero 2's success able to provide an absolutely classic lineup of songs.
The problem is that many of these songs are inaccessible or require slogs through annoying challenges to unlock… that may be fun in your own time, but we've got people round! From the unlock everything cheat, to the more fun Hyperspeed mode, to the beginner friendly No Fail mode (the one that's an absolute requirement for Through the Fire and the Flames), Guitar Hero 3's cheats menu is an absolute essential — Guitar Hero is fun on its own, but having easy access to the cheats menu makes it a party game you can fire up anytime, anywhere.
Callum: Sins of a Solar Empire: Rebellion – Sins of the Prophets
I didn't grow up with Xbox, so I never really got the Halo fandom. Even after I'd watched Red Vs Blue, which I liked, I still didn't get the Halo of it all. Then, earlier this year, I got Halo on PC, and now I kinda get it. I hadn't seen enough of the universe yet, though, so I turned to one of my favourite strategy games — Sins of a Solar Empire: Rebellion.
It's admittedly not the deepest strategy game out there, but Sins of a Solar Empire: Rebellion's real draw isn't the game itself — it's the mods. If there's a fandom, there's a Sins mod; we've got Star Wars, Star Trek, Stargate, Mass Effect, Halo and more. There's even a Babylon 5 mod with 3D models for all the ships. This game and its mods offer the perfect avenue for living out Thrawn/Adama/Cole fantasies, but that doesn't explain why Sins of the Prophets gets the spotlight.
After diving into the Halo universe, I found that one of the things I really liked about it was that humans were overwhelmingly the underdogs in it. As awesome as Reach is, it's about fighting a losing battle, and Sins of the Prophets nails that imbalance, while actually being a fairly balanced game. Fighting as the humans involves flinging ships at the enemy in hopes that they'll run out of ships before you do. Even fully upgraded, you'll still be outgunned and outsized by the Covenant.
Eduard: Final Fantasy VII's God Mode, No Random Encounters and 3X Speed "cheats"
Doublejump family, I have two horrible truths to confess: 1) I had never played the original Final Fantasy VII all the way through until this year and 2) I wouldn't have done it without the cheats baked into the PS4 port.
Now, before you reach for tomatoes, let me explain myself a little bit here. A few years ago I decided that if I loved JRPGs as much as I tell everyone I do, I should probably delve deep into Final Fantasy and play through all the mainline games. As you may expect based on the fact that I never got to Final Fantasy VII, I gave up on that ambition somewhere in the middle of playing Final Fantasy II — I just couldn't bear the grind and the random encounters anymore.
However, despite this negative experience and because I wanted to play the original before the Remake came out, I reluctantly dove into Final Fantasy VII and was thrilled to find that the PS4 port had 3X Speed, God Mode and No Random Encounters cheats baked in. At first, I decided that I wanted a "pure" experience, but when fun gave way to frustration (like it did with Final Fantasy II), I popped those suckers on… and never looked back.
I ended up having an absolute blast powering through the game and I genuinely believe that I wouldn't have finished Final Fantasy VII (and even gotten the Platinum trophy) if it wasn't for the cheats. I love those cheats so much that I want to see them become standard features in every JRPG. Square, Atlus, SEGA, whoever… just give us the option!
George: Pokémon Diamond and Pearl's Void
To understand why Pokémon Diamond and Pearl's famous void glitch (also known as "tweaking") is so special, it's important to note its purpose: the DS-era Pokémon games often allowed players to download a special item online that, when taken to the correct non-player character, would open up secret areas where mythical Pokémon like Arceus and Darkrai reside. Of course, these items were only available for a limited time, not available everywhere, or in some cases, never distributed at all; for many, getting to these areas legitimately ten years after the game launched was impossible… but the illegitimate way is arguably much more fun.
These areas were coded into the game at launch, but they were only ever designed to be accessible if the player had the correct item and went to the correct place. As such, if a player was able to warp into the area in question, then its rewards would be theirs for the taking; this might sound like a classic walk-through-walls cheat — truth be told, that's exactly what it is — but the cheat itself involves using the game's own system against it. Moving through certain tiles in Jubilife City using the bicycle set to the highest possible speed causes the game to load the graphics improperly, which enables the player to walk through walls. Of course, given that the glitch is known as the "void glitch", it goes without saying that the result sees you eventually walking through pure darkness; several coders and investigators far more knowledgeable than I ever could be were able to make their way through the darkness and create a map to areas like New Moon Island and the Flower Paradise. This glitch isn't without its consequences — you can ruin and/or lose your save file, or corrupt your game, but it ends up being worth it to run around with Darkrai, Shaymin and other unobtainable Pokémon.
I know that the expression "it's the journey, not the destination" is overplayed these days, but in this case it really does apply: the Pokémon themselves aren't all that impressive in reality, but the method to reach them is incredibly satisfying, representing a perfect balance between risk and reward. Players must glitch their whole game and stumble through literal darkness for literal hours, following a dodgy map that requires precise movements and counting in order to reap the rewards… the Pokémon themselves are more of a badge of honour at this point, and that's why I love the old school void glitch.
Jake: Pokémon's early duplication glitches
There was a time when I was a little Pokémon Master. No matter where I went, I'd be wearing my Ash Ketchum cap and carrying my Game Boy Pocket/Colour/Advance in a bag along with a battery pack, spare batteries as a backup, the light/magnifying glass extension, a Link Cable (ugh), and a couple of other games in case I got bored of Pokémon. After getting extremely lucky on a family trip and meeting someone who had both Mew and Celebi, my obsession paid off; I was the first person in my year level, and possibly even my whole school, who had a full Pokédex on Pokémon Silver. That wasn't an easy endeavour given that we didn't have social media or even online trading to seek out the last couple of Pokémon we needed, so I decided that I'd use my Pokédex to help my friends with theirs.
I've never been a big cheat, glitch or hack user in general — not due to some kind of moral objection, just because I never really felt the desire to — but helping friends out with their Pokédexes was the exception. I'd use the Pokémon duplication glitch to make copies of my Pokémon that I'd trade to my friends for a Pidgey or a Rattata, and go about my day. I'd also used the famous Old Man glitch to ensure that I had a healthy stock of Rare Candies and other items on Red and Blue, which left my chosen battle team (Arcanine, Gengar, Alakazam, Gyarados, Dragonite and Raichu; my six favourite Pokémon) all at level 100 with the best stats I could get.
In hindsight, I really should have tried to make a few bucks off it given that nobody else wanted to even attempt the glitches…
John: Turning Fallout: New Vegas into Stalker
The only time I really kit a game out with mods is when I revisit Fallout games. I don't bother with texture packs or anything else shiny, just a recipe of small mechanical tweaks. A dash more difficulty there, a pinch more damage there, and BLAM: Fallout is now a good-enough survival sim.
First up is a "Realistic Damage" mod that makes everything very, very squishy. Get hurt in any way and you'll probably be injured and need a doctor to fix your broken everything. Because Fallout enemies usually ragdoll into bloody chunks on death and combat is so condensed, encounters usually feel much better, too. Every battle is a sudden, exhilarating fight for your life. It also means you speed through the game, which is a plus.
To really sell the survival experience, I also cobble together my own Hardcore Mode. Your weapons and armour break constantly and the loot that enemies drop is broken, too. You can barely carry anything and every item has a more "realistic" weight (which usually means it's heavier). Your guns need to be reloaded manually and will also jam all the time, no matter what – better durability only makes them jam slightly less. Lighting gets an overhaul so now night-time is dark, and the game's AI was always dumb and blind so it fits right in.
On top of all that, you start with 14 S.P.E.C.I.A.L. points instead of 40, you earn five less skill points per level, and you gain experience so slowly you'll barely ever level-up anyway. Every little bit of actual ability you gain feels crucial. Just upgrading your lockpicking from Very Easy to Easy is a major achievement. You have no choice but to be a very weak idiot in a very dangerous and dimly lit world. Sure, this duct-taped bundle of mods reliably crashes my laptop every couple of hours and the lighting mods usually break, but it's worth it.
Kristian: DahrkDaiz' Mario Adventure
The big daddy of classic ROM hacks, hacker DahrkDaiz first released Mario Adventure way back in 2004. The hack is a total conversion of the NES classic Super Mario Bros. 3, already one of the most enjoyable 8-bit platformers of all time, and it takes things to a new level. Mario Adventure extends on the classic SMB3 formula with a whole new plot, additional enemies to overcome, and even the ability to switch between two items on the fly, so you can adapt to the ever-changing environment.
One of Mario Adventure's most unique features is that each level will load a completely random time of day and unique weather, including day and night cycles or even snowy conditions, making surfaces much more slippery. The Toad House also changes to let you open an item box for 300 coins, encouraging you to explore the level and collect as many coins as possible.
With a modified soundtrack and eight all-new worlds, Mario Adventure is, all things considered, a great example of what makes the ROM hacking scene so interesting. The game itself is a big challenge but it's great for anyone who loves retro platformer action, and it's one of the best ROM hacks ever made. It truly captures what makes the classic Mario games stand the test of time.
Lucas Calder: XCOM: Enemy Unknown's Long War mod
This month's Multiplayer touches on a subject close to my heart. I love mods, and as a predominantly PC-based gamer they feature heavily in a lot of my favourite games to enhance the experience. My favourite mod, hands down, has got to be Long War for the 2012 reboot of the XCOM franchise. It's a mod that was so good, XCOM: Enemy Unknown's lead designer, Jake Solomon, said that his game is "basically a 20-hour tutorial for Long War, and that's okay." While admittedly it does turn the game into a much longer experience — worthy of the theme of an elite, critically underfunded, multinational force standing against an alien invasion — the depth makes it all worth it.
Suddenly your frontline team of hardened veterans needs rest, otherwise they spend weeks in the medbay recovering from wounds and you spiral into losing rookies by the handful. You unlock more paths to weapons and armour, meaning that you never have the same experience twice (unless you're some kind of inhuman robot who can force the RNG to bend to their will!). It's got a vastly expanded roster of soldier classes so you can forge your force to suit a preferred playstyle and try out new strategies. Best of all, because you can use Notepad++ to read most of the files used to create the mod, code-savvy gamers can tweak the mod and create the very best experience for them. If there's one complaint I have about Long War, it would be that the interceptor air game is still terrible, but XCOM's focus was always on the troops on the ground anyway.
That said, I can't get enough of the game. I must have lost a hundred campaigns for the two I've completed successfully, but even in a spiral of being overrun, the mod adds so much to the base game that you persevere on the off chance you can bring it back from the brink. You almost never can, but the gameplay is so engaging you hold onto the hope you might, even when you've lost your entire alpha squad to a single cyberdisc (what are you talking about? I'm not bitter…).
Lucas Gogos: Vampire: The Masquerade — Bloodlines' The Final Nights mod
Blood is thicker than water in the real world, but in Vampire: The Masquerade: Bloodlines' case, blood is everything. We've spoken about Troika's flawed masterpiece a couple of times here on Doublejump, but Zer0morph's The Final Nights flips the game's entire premise on its head — to such a degree that the creator actually removed the "B" from their mod's official title.
The Final Nights is a mod dedicated to redesigning and improving Vampire: The Masquerade — Bloodlines' outdated and janky design. It also fixes a lot of the end-game content, which was originally so broken it was essentially unplayable. It also changes the races and classes available to you at the beginning of the game, allowing you to use a more diverse group of characters (and abilities) and giving you a lot more agency when it comes to character design. The unfortunate side-effect there is that the races and classes available in the base game are replaced, rather than being supplemented, so you'll lose the ability to play as a couple of the original clans. Aside from that, though, the story remains largely unchanged (aside from fixing some of the story events and mechanics that were broken in the original release).
The mod adds a whole new mechanic to the game that turns it into the most accurate facsimile of actually being a vampire: a Hunger meter. Using any ability throughout the game consumes some of your blood points, thus forcing you to keep yourself from getting too hungry by feeding more regularly than you'd have to in the base game — if your character gets too hungry, they'll go utterly berserk and you'll have to deal with the consequences. It makes the whole experience that little bit more challenging, and that's always welcome.
Of course, The Final Nights requires a fair bit of fiddling to actually get running, but it's absolutely worth it: it improves upon Vampire: The Masquerade — Bloodlines' base experience but also makes its end-game content entirely playable. This is the definitive way to play a game that was already well ahead of its time.
Luke: "Ultra Shortcuts" in Mario Kart Wii
Mario Kart Wii will forever be one of those games that defines a generation. It is highly likely that anyone who still has a Wii today will have a copy lying around somewhere (complete with a Wii-Wheel, remember those?) and, given enough of a reason, will reconnect it to their TV for another round of nostalgic goodness.
One reason for its continued longevity includes the fact that the Mario Kart Wii online community is still discovering new short-cuts to get completely unreal times on some of these courses. What is unique about these shortcuts is that they aren't shortcuts in the traditional sense, but they allow players to skip more than half of the course, much to the annoyance of everyone else you are playing against.
Whilst these glitches are very difficult to pull off correctly, there is a real sense of satisfaction if you manage it. Ultra Shortcuts are not like the "old-school" cheats where you enter a button and get an unlimited amount of Mushrooms; using them requires some knowledge about the game's engine and how the glitches are supposed to work, and a whole lot of good old-fashioned skill. However, the chance to discover one of these shortcuts has kept the online screen alive well past the Nintendo Wi-Fi shutdown of 2014.
Through fan made servers, players are still able to race online and set new records with these glitches. This combination of glitches to discover and an online scene that Nintendo believes is as good as finished gives the players a significant amount of freedom when playing, which ultimately contributes to players continuing to race on such an old console. These glitches and online servers don't make Mario Kart Wii the most accessible game to play online anymore, but they still provide an outlet for die-hard fans to enjoy the game far long after the last lap.
Matt: GoldenEye 007's DK Mode
If GoldenEye 007 isn't the best game ever released on the wildly successful Nintendo 64, then it's pretty damn close. For each of the James Bond tie-in's memorable moments, however, there was an equally-memorable cheat that added to its addictive, ahead-of-its-time multiplayer offering in hilarious ways — none more hilarious than the DK Mode.
DK Mode isn't technically a cheat, since you could unlock it legitimately by completing the Control mission in ten minutes or less on the Secret Agent difficulty setting, but those without that level of patience (or skill) could unlock it by putting in a button combination on the main menu screen, so we can also call it a cheat. It didn't add much to the overall gameplay other than larger character models to shoot at, DK Mode have players an iconic look: comically-large heads and arms in the style of the great Donkey Kong, for whom the mode is named after.
DK Mode was not only one of the first cheat codes I used and the source of plenty of fond memories from all those years ago, but it's also one of the first memories I have of a game developer poking fun at other franchises. I can still remember my surprise at seeing Donkey Kong being referenced in another game (that wasn't Super Smash Bros.). Because of that, DK Mode also doubles as my favourite Easter Eggs of all time.
GoldenEye 007 features some silly cheats, and some useful ones as well, but DK Mode really epitomises the silly and altogether-memorable fun that GoldenEye 007 brought — and still brings — to the table.
Max: Marvin Seo's collection of Darkest Dungeon mods
Darkest Dungeon is a game very dear to my heart, one that fostered in me a love for brutal turn-based strategy where the stakes are high and eldritch abominations are hot on your heels. At its core, Darkest Dungeon is a game about making the best of bad situations (which are plentiful and uniquely otherworldly), and it revolves around a cast of oddball "Heroes" that make up its class system.
Each hero is fine-tuned to perform a number of roles: they might heal your allies; weaken your enemies; commune with the unspeakable evils of the great beyond; or just get everyone very, very drunk. As with any strategy-based game, the real joy of strategically assembling a party of ill-begotten misfits is found in knowing just how that composition works together to achieve your goals… and that's where the Steam Workshop comes in.
The Darkest Dungeon community has used the Steam Workshop to honour the game with some truly marvellous creations, including new "hero" classes to toy with and send to their deaths. My favourite entries on the Steam Workshop are the ones that come from community figurehead Martin Seo, whose unique blend of the game's original art style and his own exceedingly-well thought-out "hero" backstories and skill mechanics have given rise to class mods that fit into the base game perfectly. Seo's modpacks fit in so well with the base game's dark, gloomy aesthetic — and his new characters so perfectly complement the existing "heroes" — that playing through Darkest Dungeon again with his mods applied felt like I was playing an official expansion, if not a whole new game.
What's best about Seo's new characters, however, is the fact that although they have a number of novel skills and mechanics, there's nothing that's blatantly overpowered or completely useless. Of course, some of them do "err" on the side of being very strong, but that's really only when you pair them with specific classes, and that's to be expected. Seo's modpacks are a truly fantastic addition to the base game, and I strongly recommend them to anyone who's played Darkest Dungeon or thinks they might be keen to give it a go; Seo's additions combine with the original game to create an experience you won't be putting down in a hurry.
Ruby: The Rosebud cheat from The Sims
The Sims is the ultimate life simulation game, setting out to faithfully recreate the human experience (occasional alien abduction or haunted clown painting aside). That includes all the heady highs of falling in love, starting a family and forging a career, as well as the dreary lows of paying bills and having ongoing expenses like food. This means that, unless you're an 18th Century aristocrat eagerly calling out to your butler "why look, Jeeves, I'm experiencing what it is like to pay taxes, how quaint!", you're gonna want some cold hard cash in order to start living out your lottery-winner fantasy as soon as possible. Opening the Cheats Bar and typing in Rosebud nets you a cool thousand Simoleons — or you can whack in Motherlode for 50k if you have visions of your Sim diving into a pool of cash like Scrooge McDuck.
I always like to use Rosebud at the start of a new Sim's journey, just to give them an edge up on the virtual competition. Better gear gets your Sim's skills levelled up faster, and without needing to work for a living they can spend all afternoon pumping iron on the gym set before a riveting five hour game of chess against themselves to increase their Logic. Once they're suitably maxed out, I set them on a career path like Politics and watch them climb the ladder as fast as their tasteful pantsuit can handle.
Of course, when using money cheats there's a risk of sapping all the challenge right out of the game. Once your Sim has access to unlimited funds, they don't really need to work. They could buy another painting for their mansion, or upgrade the shower, but they don't have to. Even if their performance at work slumps, with a golden ticket at your fingertips, they never have to go without. Their life just becomes a meaningless cycle of days, barely going through the motions, until one day the ladder disappears while they're in their Olympic-sized swimming pool and they're never seen again… Huh, I guess it really is the ultimate life simulation game.
Tom: Grand Theft Auto: Vice City's "Spawn Tank" cheat
Grand Theft Auto's and cheats are a match made in gaming heaven — which, in this case, is a sprawling metropolitan world designed to facilitate your every anarchistic and criminal fantasy. A more grounded option than the lunacy provided by the Saints Row franchise, GTA: Vice City brought vibrant chaos to the previously dreary GTA entries with Hawaiian shirts and giant purple dildos to beat down your enemies.
Then there was the infamous "Spawn Rhino Tank" cheat on Xbox which, once upon a time, I had memorised as dearly as my home phone and parents' mobile numbers (B, B, LEFT TRIGGER, B, B, B, LEFT TRIGGER, WHITE, RIGHT TRIGGER, Y, B, Y). Going on an unstoppable rampage, annihilating the denizens and police of Vice City until the army themselves came to put you down was one of the most ridiculous and cathartic moments of gaming joy I have ever experienced. Even actually spawning the tank was hilarious, given that it would usually drop in the most inconvenient place possible and/or crush a bunch of non-player characters' vehicles when it did.
Just thinking about this cheat brings memories of hand-written cheatsheets, dial-up internet and even the near-extinct gaming magazines. One always had to prepare for raucous cheat-enabled rampages with a manual save, since activating god modes in the older Grand Theft Auto titles would nullify any and all achievements, but I don't think I've ever had as much silly fun in an open-world game as I did with Vice City and its cheats. Outside of the Rhino Tank, I also stacked Road Rage (which made NPC vehicles attack you), Proximity Explosion (which made any cars too close to you explode), and Flying Vehicles (which does what it says on the tin); that combination had me flying around above the streets of Vice City as sedans, trucks and motorbikes careened up and down towards me and exploded violently, all while I rained artillery fire down on the environment below to create the ultimate fireworks display.
While I greatly enjoyed Grand Theft Auto: San Andreas, Vice City will always be my favourite entry in the series for its stylised violence — in large part due to these cheats. It's because of this that I could never enjoy GTA IV, which saw Rockstar Games go back to the dreary cityscapes and sucked all the fun out of it. Simpler times lead to simpler fun.
Talking about cheats makes some of us feel omnipotent, it makes some of us feel nostalgic, and it makes some of us feel dirty. No matter how it makes you feel, jump into the comments section below, our Discord server or our Facebook group and let us know what your favourite cheats have been!
Doublejump
Doublejump has been an independent voice in Australian games journalism since 2012. Its writers are passionate, talented, and all-round good people and its owners are proud of Doublejump's core values of acceptance, tolerance, and respect.

redpajama_set_name: RedPajamaCommonCrawl


Think about maintaining your normal body core temperature, whether inside and outdoors during an extended emergency summer power outage.
These vests feel like terry cloth but have tiny pockets of highly absorbable beads that can take in water and expand to 6 times their dry size. The vest is soaked in cool water and gently wrung out to remove excess. The vest is placed over a t-shirt and cools by evaporation; the air moves faster next to the water-logged beads, which creates a layer of cool air between the vest and the skin. Evaporative cooling vests are light weight, inexpensive, and there is no need to purchase a second vest to swap; the vest can be re-wet and immediately used again. Evaporative cooling apparel is not limited to vests; headbands, wristbands, floor mats, and even dog vests are available for purchasing. If an evaporative vest is damaged, it can be re-sewn by hand. The function of the vest isn't seriously compromised if a few beads escape. (The beads are non-toxic, but always check the vest carefully to avoid ingestion by a child.) Evaporative cooling vests are of limited benefit in humid environments and are sometimes not tolerated by individuals with sensitive skin due to the slight dampness of the garment.
This type of vest contains inserts that are activated by placing them in the freezer or a container of ice water, and then the inserts maintain a consistent temperature (usually 53-56 degrees F.) for up to three hours. The inserts can then be re-activated (10 to 20 minutes for activation) and reused. Many people choose to purchase an extra set of inserts and rotate them, so that the vest can be used continuously. The inserts are not exactly ice packs; they do not reach freezing temperatures so they are unlikely to cause damage if left in contact with bare skin. This makes them safe to use with young children or individuals who are unable to feel heat or cold due to neuropathy or communicate discomfort. They are activated when exposed to temperatures above freezing, and need much less time to recharge than an actual frozen ice pack would take. Also, the inserts do not "sweat" when the cold is being transferred to the wearer, so clothing stays dry. Phase change vests can be made to fit wearers of all ages and sizes, custom vests can be made for individuals weighing more or less than the displayed vests are recommended for.
There are drawbacks to purchasing and using phase change vests. The inserts add weight to the vest, from 1 ½ to 2 lbs for children's vests to 4 lbs or more for 3X or 4X adult sizes. Fortunately, the weight is evenly distributed on the body and is close to the individual's center of gravity, so the balance issues associated with backpacks or weights shouldn't be a problem. The cooling vest system is much more expensive than an evaporative vest; you can expect to pay around $200 for a vest and two sets of inserts. The phase change inserts are filled with a viscous fluid and are durable but not indestructible. If an insert is damaged it must be discarded and replaced.
This vest combines the benefits of the evaporative as well as phase change vests. The user has the ability to choose between using the evaporative or phase change cooling methods, and can also choose to use both systems simultaneously to complement one another. This type of vest is new to the market, but customers who have purchased hybrid guests have reported high satisfaction rates.
These vests look just like phase change cooling vests, but use actual ice packs that freeze at 32 degrees or in some cases, even colder. These cold packs give the highest level of cooling because the cold packs are the lowest temperature. These vests are effective in extreme humidity and very high temperatures. Extra packs can be added or changed out over time.
There are several drawbacks to cold pack vests. The frozen inserts are generally heavier than phase change inserts, are usually inflexible when frozen, and must be returned to an actual freezer, below 32 degrees farenheight, to be refrozen, which can take several hours. Most frozen packs "sweat" while discharging cold energy, which some individuals may find uncomfortable. Most importantly, ice packs cannot be applied directly to skin and should never be used by individuals who may have impaired sensation, are asleep, or unable to communicate discomfort, as frostbite and serious injury can occur.
1. WHO NEEDS A COOLING VEST?
If work, leisure activities or medical conditions make you uncomfortably hot and/or affect your performance, you could benefit from a Cooling Vest.
2. WHAT IS HEAT STRESS?
Heat stress occurs when the body's reaction to the environment causes its core temperature to rise above safe limits. This can result in a racing heart, profuse sweating, dizziness, reduced energy and slowed reaction times. This reduces safety, decreases efficiency and lowers productivity.
What is the difference between the many different types of body cooling systems available?
There are many different cooling products available and the best one for you depends on your personal situation, activity and environment. We recommend you consult your health care professional prior to purchasing a cooling garment or system.
Evaporative Cooling: These products come in an assortment of garments that fit a wide variety of locations on the body. They are soaked in water to charge special polymer materials built into the garments. As the water evaporates (sometimes over several days), the garment provides surface cooling. These systems are typically low cost and light weight.
Cold pack cooling: These products typically come in vests, neck coolers and wrist coolers. The products work by incorporating cold packs into pockets of the wraps. The cold packs are placed in a freezer or a refrigerator until ready for use and then are placed in pockets designed into the wraps. The packs will stay cold for 2 to 4 hours depending on environmental conditions.
Disadvantages: Requires access to freezer / refrigerator requires time for packs to freeze medium weight: 4-5 lbs.
Phase Change Cold Pack Cooling: These products are similar to the cold pack systems only use a phase change polymer in the cold packs or the garment. This technology controls the release of temperature to a specific range through out the cooling cycle. A typical temperature is 58 degree F. Phase change cold packs may be recharged in the freezer, refrigerator or in ice water.
Disadvantages: Higher cost system, high cost of spare packs Lower cooling efficiency than cold packs medium weight: 5-7 lbs. medium cooling capacity.
Active Cooling: These products typically incorporate a coolant, often ice water, that is circulated from a reservoir by a pump system through channels or tubes embedded in a vest. Often a hood for the head is incorporated into the system also. The temperature of the circulating coolant usually can be adjusted. The system operates on batteries, house or car current. This type of system will provide many hours of cooling before the ice and water needs to be recharged.
Advantages: Most effective cooling – core body cooling adjustable cooling temperature extended cooling time between recharges no wetting required, works in all environments light weight garments.
Disadvantages: Very high cost system tethered system limits mobility requires ice water reservoir.
I have this vest and it works well, it does keep you cool out doors at temperatures of around 100F while doing light to medium work . I prefer using this, the "phase change" vest for "in the house" applications when the power is out. It's dry and doesn't damped furniture; for for a similar reason, I prefer the evaporative vest, discussed below, for outdoor use.
RPCM® Cooling Vests feature side elastic straps and over-the-shoulder adjustability to fit a wide range of body sizes. RPCM® Cool Vests provide you with the maximum comfort available in the market today. They maintain a cool, constant 59°F/15°C temperature for up to 2½ hours, weigh less than 5 lbs., and recharge in minutes. The RPCM® Cool Vest is extremely durable. It can be easily cleaned in regular laundry. .
> RPCM® Cool Packs quickly recharge in only 20 minutes in ice water. The packs charge (freeze solid) at a temperature about 50 degrees. There are 3 ways to fully charge the packs. They will be rock solid even using the refrigerator which is my favorite of the 3 ways.
__1) On the road toss them in a plastic bag full of ice for 30 minutes.
__2) Put them in the freezer for 1 hour.
> RPCM® Cool Vests are Glacier Tek's exclusive Patent-Pending technology that uses a unique "green" formula.
> RPCM® contains absolutely no hazardous ingredients or chemicals and is completely non-toxic.
> Vest weigh less than 5 lbs.
Q. Is the material in the RPCM® Cooling Vest hazardous?
A. No. The phase change material in the RPCM® Cool Pack is unique among phase change materials used for cooling. It is the only phase change cooling vest on the market which contains no hazardous ingredients or materials. It is also non-toxic, safe, and environmentally friendly. Should the RPCM® Cool Pack become punctured and leak onto your skin, it may be washed off with soap and water.
Q. How many times can the RPCM® Cooling Vest be used?
A. If the RPCM® Cool Packs are not punctured or torn, they can be used indefinitely. Our RPCM Cooling Vest has no shelf life. Some of our cooling packs have been recharged 10,000 times with no measurable change in performance.
Q. Can I store my cooling vest in the freezer?
A. Yes, the RPCM® Cooling Packs can be deep-frozen indefinitely without affecting performance.
Q. How long do RPCM® Cooling Vests take to recharge?
A. Typically 20 minutes in ice water will fully recharge a set of cooling packs, longer in a freezer or refrigerator. They recharge more quickly in ice water because of the conductive method of heat transfer. In a freezer, they chill convectively, which takes longer. They can be stored in a refrigerator or freezer indefinitely without damage or loss of functionality. Recharging in a cold freezer with the door kept shut takes about an hour. In a refrigerator, it can be several hours to overnight, depending on the heat load, how many times the refrigerator is opened, etc.
Q. What are the benefits of RPCM® Cool Packs over ice or frozen gel packs?
RPCM® Cool Packs operate at a much more comfortable 59° F (15°C) temperature. That means they can't cause skin or tissue damage or cause extreme discomfort like ice or frozen gel can do.
RPCM® Cool Packs will be effective for a longer period of time between charges. The reason? The difference in temperature between ambient (surrounding) air and the phase change product is much less than the difference in temperature between ambient air and ice. That means more cooling is absorbed by the body and less is lost to the air.
RPCM® Cool Packs are cooled to a temperature that is usually above the dew point. That means they normally won't condense or sweat against your body or clothing. Ice and frozen gel packs are below the dew point, so they sweat, making them uncomfortable to wear and adding to the weight of the vest or jacket. Condensation also robs the ice pack of efficiency because condensation creates heat, which is absorbed by the pack, further reducing its efficiency.
Q. How do RPCM® Cooling Vests compare with evaporative-type products?
A. RPCM® Cooling Vests provide much greater efficiency and better performance. Evaporative-type products by design retain water, so are always wet and can grow bacteria. This makes them uncomfortable against your skin. It also means they will grow mildew quickly over time, as they rarely dry out. Further, evaporative-type products can't operate in high humidity environments (or under protective clothing,) because the atmosphere is already saturated with water, so there is no place for the evaporation to go. RPCM® Cooling Vests, on the other hand, are unaffected by humidity.
Q. Will RPCM® Cooling Vests reduce body core temperature?
A. Our products are worn to help maintain a normal body core temperature. The purpose of phase change cooling technology is to help maintain a comfortable core temperature and prevent that temperature from increasing above normal. It's our goal to help you avoid heat stress in the first place.
Q. Isn't water a phase change material?
A. Yes. A phase change occurs whenever matter changes from one form into another. Water can change from a solid (ice) to a liquid, as well as to a vapor. Water changes into a solid at a specific temperature: 32ºF (0°C). But RPCM® Cooling Vest packs change into their solid form at 59º F (15°C). Since water changes into its solid form at a much lower temperature, it loses more of its cooling ability to ambient (surrounding) temperature. It's also below the dew point, so it causes condensation as it melts. Further, it's uncomfortable and requires an overnight stay in the freezer to refreeze.
Q. Will RPCM® Cooling Vests cause vasoconstriction?
A. That's one of the advantages of RPCM® Cooling Vests: They function within a comfortable temperature range that unlikely to promote vasoconstriction of blood vessels, unlike ice or frozen gel which promotes rapid vasoconstriction. This is an important benefit, as non-constricted blood vessels allow your circulatory system to freely move blood throughout your body, then release heat at the skin surface. With ice, the body is fooled into defending itself agains the intense cold. It reacts by constricting the blood vessels near the skin, limiting the body's natural cooling system. The heart and lungs then have to work harder, expending extra energy in the chest cavity and creating yet more body heat and other risks.
Q. Do RPCM® Cooling Vests come in sizes?
A. No. The RPCM® Cooling Vest is adjustable across a wide range of sizes to enable it to fit many people. Inventories of various sizes are reduced and one vest may be adjusted to fit several people, enabling sharing of the product from person to person. It adjusts over the shoulders and around the waist for a comfortable fit in a wide range of body sizes.
Q. Where can I purchase Glacier Tek Products?
A. Glacier Tek, Inc. wishes to offer you the most expedient service possible, and allows you to choose from several ordering options: Order On-Line, Fill out an Information Sheet, or call us at 800-482-0533 for more information or to locate a distributor near you. Thank you for your interest in Glacier Tek, Inc. and our cooling technology products.
[Photo at left] TechNiche Deluxe Hyperkewl Evaporative cooling vest, Large size (40-42),, silver colored exterior, $49.99: High mandarin collar, front pockets, and zipper closure combine to offer the ultimate cooling and sun protection solution.
The evaporative vest works, I have one and prefer it for outdoor use. I've tested it doing my afternoon walks at temperatures of about 100F.
Improved HyperKewl™ Evaporative Cooling Fabric ((PEF6519) – Helps our Evaporative Cooling products to last longer, and withstand more wear and tear. No gel or beads. This simple and effective technology works by combining water with our HyperKewl™ Fabric to create garments that gradually release water through evaporation to keep you cool and comfortable. Comfortable quilted Oxford nylon outer w/ polymer embedded fabric inner, water repellent nylon liner, and black poly-cotton trim.
Provides 5-10 hours of cooling relief per soaking; lightweight, durable and washable.
* Between use the vests are each hung on a sturdy wide shouldered clothes hanger.


IMMACULATE TOWN HOME IN FANTASTIC LOCATION!First floor entry features large secondary bedrooms & full bath.Second floor boasts beautiful kitchen that boasts granite counters,stainless appliances,built in microwave,gas stove top,separate pantry & island breakfast bar that is open to l breakfast area & spacious living rm w gas log fireplace & balcony.Master suite features walk in closet,dual vanities oversized separate shower & deep soaking garden tub.Third floor features another living area currently being used as a media room.This would also make a wonderful second master bedroom suite as it has a full bathroom & walk in closet.This area also leads to a huge patio with balcony that is perfect for relaxing.
I was searching for a Property and found this listing (MLS® #14059824). Please send me more information regarding 4417 Riverview Drive, Carrollton, TX, 75010-4263. Thank you!
I'd like to request a showing of 4417 Riverview Drive, Carrollton, TX, 75010-4263 (MLS® #14059824). Thank you!


Human beings are naturally drawn to lights thus tend to invent various means to imitate sunlight in order to expel darkness. This installation image is composed of 50-70 bright vertical lines. These vertical lines will follow the audience's footsteps and change its shape, as if the digital lines are given life. The audience will experience infinite lights.


This immaculately presented apartment is located within the very sought after complex of Puerto Marina with easy access to supermarkets and the local restaurants and bars and only 10 minutes to the lovely beaches of the Mar Menor.
The property offers 3 double bedrooms and 2 bathrooms (1 en-suite) and comes with an underground parking space included.
Puerto Marina is a gated secure complex, and is very disabled friendly with ramps throughout the complex and the swimming pool.


Nowadays, almost every Internet user has a home router with WiFi. As a result of particular importance to protect and encrypt hotspots. How can you effectively protect the WiFi network and prevent the leak of valuable data? You have to only properly configure the router.
The least security issues are residents of single-family homes. I am far from a neighbour, so the problem is solved. Of course, one can always approach the house. However, it is disposable. No one will break into our house in order to steal WiFi. In the block where many apartments are located close to each other. You can then catch a signal of one's network. If no security, then anyone can connect to any of them. Not need their own Internet access.
A few years ago, detection of an intruder in the home network was easy. The presence of unauthorized persons clearly reduced the speed of data retrieval.
Now the links are fast and it is hard to see if anyone uses it outside of us, when on that we do not know. Many novice users hotspots knows about the existence of the network unprotected. These networks are not secured by any password, so everyone can connect to the WiFi network. This practice should be avoided. Some networks are secured. There, you have to enter a password the first time, or any combination. These networks are protected and encrypted. The password is our first line of defence against intruders. Thanks effectively discouraged 99% of the intruders. Most often amateurs. With a choice of several Wi-Fi network they will seek such an option, which does not demand from them the code.
The password should contain more than 8 characters.
They should be ready words. As for such, which can be found in dictionaries. To this must be in the numbers and special characters. It is good numerals and characters to replace letters. We have, for example, the name of our girls. Such kind of password is easy to remember. Let it is called: JULIE MARIE CLAIRE. Converts up letters to numbers or characters that look similar.
In this way, you can remember a password without any problem and it contains characters and numbers. This trick significantly increases the complexity of the password. Rather than re-invent the password yourself, we can also give his creation a special software called password generator. It will prepare us totally random string of characters.
Securing access to WiFi networks involves much more than just adding a password.
Authentication is only one of several pieces of the puzzle to protect our data. The second, equally important, is the encryption of data transferred between the router and the computer, tablet or smartphone. Another important element of security is called. MAC address filter. It works on the principle of white or black list, which allows or blocks a specific device. Each laptop, tablet or smartphone (specifically their NICs) has so-called physical address written in hexadecimal (digits 0-9, the letters A-F). At the end it is worth mentioning a few less critical but still favourable from the point of view of safety practices. First, you must change the default SSID, the name of the network on their own. This is possible through the main settings of the Wi-Fi router. Thanks to gain a greater resistance to some of hacker attacks.


text:
HBCU Baseball Programs Scheduled to Open 2021 Season in a Matter of Days
Edward Waters College opens the 2021 college baseball season for Historically Black College and University baseball programs in a matter of a few days. All eyes are on the upcoming opening weekend with Edward Waters, then followed by Rust College, Florida Memorial University, Tougaloo College, Claflin University and Stillman College which start their respective schedules. All matchups will be premier non-conference contests.
Edward Waters kicks off the season January 29th on the road with No. 15 ranked Keiser University in the NAIA Top 25 Coaches Poll. The opener is a four-game series with two scheduled doubleheaders. First game is slated to start the HBCU baseball season at 11:00 a.m. and can be seen live.
Rust College's home opener is a doubleheader on February 2nd at noon CT with Blue Mountain College. This is the first time meeting for these programs. The game is scheduled at the Rust Bearcats field in Holly Springs, Mississippi.
Florida Memorial starts its season on the road February 5th with a meeting of its long-time archrival Edward Waters at historic J.P. Small Park in Jacksonville, Florida. The matchup will be a three-game series with a single game to open that series followed by a doubleheader. All games can be seen live on the FMU network.
Tougaloo College opens a four-game home series (two doubleheaders) on February 6th verses Marian University. The four games will be played on the home field of the Tougaloo Bulldogs.
Claflin starts a three-game home series starting with a doubleheader February 6th, and a single game to close out the series hosting the University of North Georgia at Historic Marmow Field.
Stillman will open the 2021 season Saturday February 7th on the road in doubleheader action traveling to Laurel, Mississippi taking on Southeastern Baptist College at Wooten-Legion Field.
HBCU Baseball slated games:
1/29 Edward Waters v. Keiser University DH 12 p.m. Game 1 & 2 West Palm Beach, Fl Live Livestats
1/30 Rust v. Blue Mountain College DH 12 p.m. Game 1 & 2 Blue Mountain, Ms
2/2 Rust v. Southeastern Baptist College DH 12 p.m. Game 1 & 2 Holly Springs, Ms
2/5 Florida Memorial v. Edward Waters 5 p.m. Jacksonville, Fl Live
2/6 Florida Memorial v. Edward Waters DH 1 p.m. Games 1 & 2 Jacksonville, Fl Live
2/6 Tougaloo v. Marian University DH 12 p.m. Games 1 & 2 Tougaloo, Ms
2/6 University of North Florida v. Claflin DH 1 p.m. Games 1 & 2 Orangeburg, SC.
2/7 Stillman v. Southeastern Baptist College DH 12 p.m. Game 1 & 2 Laurel, Ms
2/7 University of North Florida v. Claflin 2 p.m. Orangeburg, SC.
← Grambling State and Prairie View A&M Set to Meet in State Fair Diamond Classic
Podcast: Black College Nines Talks Baseball With North Carolina A&T Head Coach Ben Hall →


The birdie putt on No. 10, maybe a six-footer, rolled toward the hole, destined for glory. At least, that's what Justin Thomas thought. He figured he had read it perfectly. He waited for the ball to drop and the roar from the gallery gathered around the green there at the Quail Hollow Golf Club in Charlotte, N.C.
Except the Titleist IV didn't drop. It hung there on the lip, teasingly. For 12 seconds, it hung on the lip while the gods of golf debated on whether Thomas, the 24-year-old prodigy from Louisville, deserved to be rewarded as he attempted to win the 99th PGA Championship, one of golf's four major titles.
Now 12 seconds may not seem like a long time. A fast thoroughbred can run an eighth of a mile in 12 seconds. A baseball can go from a bat to bleacher seats in less than 12 seconds. But when you're a pro golfer trying to win your first major against the best field in the world, well, 12 seconds is an eternity.
It was long enough for Thomas to turn his back to the hole and say a few choice words before he spun back around to watch, agony twitching at the edges of his smile.
Then the ball dropped into the hole.
The gallery exploded in joy.
And a semi-dazed Thomas exchanged a fist-bump with caddy Jimmy Johnston, doffed his blue Titleist baseball cap and bowed to the gods of golf, and then did an exaggerated shrug for the crowd and cameras, much as North Carolina basketball god Michael Jordan had done after making an impossible shot in an NBA playoff game.
Of all the amazing shots that Thomas made on his way to a final-round 68 and a two-shot victory over runnerups Patrick Reed, Francisco Molinari, and Louis Oosthuizen, the 12-second putt on the lip will be remembered and celebrated far more than his 14-foot bogey putt on No. 1, his long snake of a putt for a birdie on No. 9, the birdie on No. 13 that enabled him to break away from the pack, and the birdie on the par-three 17th that pretty much sealed the deal.
The only sour note, at least for fans in Thomas' hometown of Louisville, Ky., was that Justin was introduced as being from someplace in Texas as he walked onto the final green to much applause and cheering. He may be living in Texas now, but come on. Justin is as much Louisville as Churchill Downs and Cherokee Park.
A grandson and son of PGA club professionals, Justin learned the game from his father, Mike, who has been the pro at Harmony Landing golf club, just off U.S. 42 in Goshen, for about as long as Justin has been on this earth. To this day, Mike is his coach. Justin also went through Louisville's Catholic School system, graduating from St. Xavier in 2011.
Texas? That's the home state of Jordan Spieth, who is Justin's closest friend on the Tour. It's the home of Reed, who was able to tie for second when Kevin Kinser, who led most of the tournament, faltered on the back nine of the final round. And, yes, Texas is the home of golfing legends Ben Hogan, Byron Nelson, and Ben Crenshaw.
But Thomas belongs to Louisville every bit as much as Bobby Nichols, the only Louisville native who had won a golf major until yesterday. Like Thomas, Nichols graduated from St. Xavier. Also like Thomas, his first – and only – major came in the PGA. That happened in 1964 at the Columbus Country Club, when Nichols went wire-to-wire and withstood a late charge by Jack Nicklaus on his home course.
At the time, Nichols was 32, or eight years older than Thomas is now, and he didn't engender the kind of anticipation that now surrounds Thomas. This was Justin's fourth victory of the year, most on the Tour, and CBS announcer Jim Nantz floated the idea that he might be the front-runner for Player of the Year.
Known in his younger days for impatience and having a bit of a temper, Thomas was a model of cool in Charlotte's heat. Although he said he "acted like a child and threw a little tantrum" while the ball was hanging on the lip on No. 10, nobody noticed. He looked like he was resigned to being another dogged victim of inexorable fate, as a long-gone writer described the game.
But then dang if the ball didn't drop.
Thomas might have won if the putt had stayed on the lip, but making it certainly put him into a winning frame of mind. There's nothing like getting a sign from the golf gods that they're smiling on you.
So when there was a five-way tie for the leader after 12 holes, it was Thomas who made another birdie while his rivals were missing greens and putts. Suddenly Justin was alone at the top, but he didn't change his game plan.
For the record, Thomas shot 73-66-69-68 for a 276 total. He earned $1.89 million. But most importantly, he certified the talent and potential that has defined him ever since he was a kid hitting shots on the Harmony Landing practice tee until it got too dark to see.
Like almost everyone else on the Tour, where the difference between great and merely good is a thin a margin as there is in sports, Thomas is dedicated to this craft. However, his dad did admit earlier this year that he's something of a clothes horse who owns a ton of golf apparel and shoes.
He won the PGA Championship wearing a dark pink shirt with only a Polo logo on it, a start contrast to Kinser, who wore so many logos on his cap and shirt that he came as close to looking like a NASCAR driver as a golfer can come. But that, too, will change. Young and handsome, Thomas will spend the winter sorting through all kinds of endorsement opportunities.
Stuff like that happens when the golf gods decide that it's your turn.