| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- // ==UserScript==
- // @name High-Low
- // @namespace http://tampermonkey.net/
- // @version 0.1.10
- // @description try to take over the world!
- // @author You
- // @match https://www.torn.com/loader.php?sid=high*ow
- // @require https://cdn.jsdelivr.net/npm/vue/dist/vue.js
- // @resource sourceCodePro https://fonts.googleapis.com/css?family=Source+Code+Pro
- // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/highlight.min.js
- // @resource json-formatter_css https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/styles/default.min.css
- // @resource pure https://unpkg.com/purecss@1.0.1/build/pure-min.css
- // @resource rocker https://relentless.rocks/rocker.css
- // @grant GM_getResourceText
- // @grant GM_addStyle
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- /* jshint -W097 */
- /*global
- $, console, Raven, GM_addStyle, GM_getResourceText, Vue, hljs
- */
- (function() {
- 'use strict';
- var sourceCodePro = GM_getResourceText("codeSourcePro");
- GM_addStyle(sourceCodePro);
- GM_addStyle("pre,code {font-family: 'Source Code Pro', monospace; font-size: 14px;}");
- var js_css = GM_getResourceText("json-formatter_css");
- GM_addStyle(js_css);
- //var bootstrap_css = GM_getResourceText("bootstrap_css");
- //GM_addStyle(bootstrap_css);
- let pure = GM_getResourceText('pure');
- GM_addStyle(pure);
- let rocker_css = GM_getResourceText('rocker');
- GM_addStyle(rocker_css);
- GM_addStyle(".hljs-number { color: blue; }");
- var formatterConfig = {
- hoverPreviewEnabled: false,
- hoverPreviewArrayCount: 100,
- hoverPreviewFieldCount: 5,
- theme: 'dark',
- animateOpen: true,
- animateClose: true,
- open: 20
- };
- var changeTimeout = function() {
- var oldTimeout = setTimeout;
- /*global setTimeout:true */
- setTimeout = function(a, b) {
- return oldTimeout(a, b/3);
- };
- console.log("setTimout: changed");
- };
- let script = document.createElement('script');
- script.appendChild(document.createTextNode('('+ changeTimeout +')();'));
- (document.head || document.body || document.documentElement).appendChild(script);
- class Card {
- constructor(number) {
- this.number = parseInt(number, 10);
- let card = this.getCardFromNumber(this.number);
- this.color = card[0];
- this.rank = card[1];
- }
- getCardFromNumber(number) {
- let mod = (number-1) % 4;
- let color = "";
- if (mod === 0) {
- color = "spades";
- }
- if (mod === 1) {
- color = "diamonds";
- }
- if (mod === 2) {
- color = "hearts";
- }
- if (mod === 3) {
- color = "clubs";
- }
- let offset = 0;
- offset += 4; // Counter for 2 being first card, not 1
- offset += 3; // Counter for using floor
- let rank = Math.floor((parseInt(number, 10)+offset)/4);
- return [color, rank];
- }
- toString() {
- let rank = this.rank.toString();
- console.log("rank:", rank);
- /* if (rank === "10") {
- rank = "T";
- } */
- if (rank === "11") {
- rank = "J";
- }
- if (rank === "12") {
- rank = "Q";
- }
- if (rank === "13") {
- rank = "K";
- }
- if (rank === "14") {
- rank = "A";
- }
- return this.color + "-" + rank;
- }
- toValue() {
- return this.rank;
- }
- }
- /* global */
- let action = {};
- let formula = {};
- let won = 0;
- let lost = -1;
- let ratio = '0.000000';
- /* Initialize deck */
- let deck = GM_getValue('deck', []);
- let createDeck = (deck) => {
- for (let i = 2; i < 54; i++) {
- deck.push(i);
- }
- GM_setValue('deck', deck);
- console.warn('new deck.length:', deck.length);
- // console.log(deck);
- action.cards = deck.length;
- return deck;
- }
- if (deck.length === 0) {
- deck = createDeck(deck);
- }
- let removeCard = (deck, card) => {
- /*
- console.log('[removeCard] card:', card);
- console.log('typeof card:', typeof card);
- console.log('typeof deck[5]:', typeof deck[5]);
- */
- for( var i = 0; i < deck.length; i++) {
- if ( deck[i] === card) {
- deck.splice(i, 1);
- }
- }
- GM_setValue('deck', deck);
- action.cards = deck.length;
- // console.log('deck.length:', deck.length);
- }
- //********
- // Controller
- //********
- let reset = () => {
- // Reset
- // See https://openuserjs.org/install/DeKleineKobini/TORN_HighLow_Helper.user.js
- $(".actions-wrap")[0].style = "display: block";
- $(".actions")[0].appendChild($(".startGame")[0])
- $(".startGame")[0].style = "display:inline-block";
- $(".low")[0].style = "display: none";
- $(".high")[0].style = "display: none";
- $(".continue")[0].style = "display: none";
- }
- let processStartGame = function(db) {
- let formulaStats = db.DB.formulaStats[0];
- let previousMultiplier = 0;
- let currentMultiplier = 0;
- if (formulaStats) {
- currentMultiplier = formulaStats.currentRatio;
- previousMultiplier = formulaStats.previousRatio;
- if (previousMultiplier !== currentMultiplier) {
- console.log("Multiplier changed!. Old: " + previousMultiplier + " => New: " + currentMultiplier);
- }
- }
- console.log("Multiplier:", currentMultiplier);
- //$("pre code.json").empty().append(JSON.stringify(db, null, 4));
- console.log('myVue:', myVue);
- myVue.jsonobject = JSON.stringify(db, null, 4);
- // myVue.jsonobject = "Test";
- // action.header = "Test";
- Vue.nextTick(function() {
- hljs.initHighlighting.called = false;
- hljs.initHighlighting();
- });
- reset();
- };
- let processGameStarted = function(db) {
- // dealerCard is revealed; player picks High or Low
- // Note: Player also has the option to cash in but that is never considered
- // console.log("dealerCard:", db.currentGame[0].dealerCard);
- let dealerCard = new Card(db.currentGame[0].dealerCard);
- // console.warn('dealerCard.number:', dealerCard.number);
- removeCard(deck, dealerCard.number);
- if ('result' in db.currentGame[0]) {
- console.log('LOST');
- removeCard(deck, parseInt(db.currentGame[0].playerCard, 10));
- }
- console.assert(dealerCard.toString() === db.currentGame[0].dealerCardInfo.classCode,
- "Mismatch dealerCard " + dealerCard + " <-> " + db.currentGame[0].dealerCardInfo.classCode);
- console.log("dealerCard:", dealerCard.toString());
- let arrayWithOdds = calculateOdds(dealerCard, deck);
- let lower = arrayWithOdds[0];
- let higher = arrayWithOdds[1];
- let numberOfCards = arrayWithOdds[2];
- // testing
- //$('div.action-c.action-btn-wrap.active.low').addClass('iconPulseExpiring');
- //$('div.action-r.action-btn-wrap.active.high').removeClass('active');
- $(".startGame")[0].style = "display: none";
- if (lower >= higher) {
- $(".high")[0].style = "display: none";
- $(".low")[0].style = "display: inline-block";
- } else if (higher > lower) {
- $(".low")[0].style = "display: none";
- $(".high")[0].style = "display: inline-block";
- }
- };
- let processMakeChoice = function(db) {
- // The deal has ended. The choice is cash in or play on.
- if (db.currentGame[0].dealerCard !== db.currentGame[0].lastDealerCard) {
- // Reveal dealerCard of next deal
- // Page has been refreshed
- // There is no playerCard (there is a lastPlayerCard)
- db.currentGame[0].playerCard = db.currentGame[0].lastPlayerCard;
- db.currentGame[0].playerCardInfo = db.currentGame[0].lastPlayerCardInfo;
- // dealerCard assert will fail!
- }
- console.log("step:", db.currentGame[0].step);
- let dealerCard = new Card(db.currentGame[0].dealerCard);
- console.assert(dealerCard.toString() === db.currentGame[0].dealerCardInfo.classCode,
- "Mismatch dealerCard " + dealerCard + " <-> " + db.currentGame[0].dealerCardInfo.classCode);
- let playerCard = new Card(db.currentGame[0].playerCard);
- console.assert(playerCard.toString() === db.currentGame[0].playerCardInfo.classCode,
- "Mismatch playerCard " + playerCard + " <-> " + db.currentGame[0].playerCardInfo.classCode);
- console.log("playerCard:", playerCard.toString());
- removeCard(deck, parseInt(db.currentGame[0].playerCard, 10));
- /*
- if (db.DB.deckShuffled) {
- console.log('[processMakeChoice] deckShuffled', db.DB.deckShuffled);
- // New deck
- deck = [];
- deck = createDeck(deck);
- }
- */
- };
- $(document).ajaxSuccess(
- // On every detected Ajax communication
- function(event, jqxhr, settings, data) {
- // Make sure it was to or from /loader.php?sid=hiloJson&rfcv=<rfcv>
- if (settings.url.indexOf("loader.php?sid=hiloJson") != -1) {
- //console.log("event:", event);
- //console.log("jqxhr:", jqxhr);
- //console.log("settings:", settings);
- let db = JSON.parse(data);
- // $("pre code.json").empty().append(JSON.stringify(db.currentGame, null, 4));
- myVue.jsonobject = JSON.stringify(db.currentGame, null, 4);
- // hljs.initHighlighting.called = false;
- // hljs.initHighlighting();
- /*
- Vue.nextTick(function() {
- hljs.initHighlighting.called = false;
- hljs.initHighlighting();
- });
- */
- console.log("db:", db);
- if ("currentGame" in db && "result" in db.currentGame[0] && db.currentGame[0].result === "Incorrect") {
- db.status = "Incorrect";
- }
- let status = db.status;
- console.log("db.status:", db.status);
- myVue.header = status;
- if ('DB' in db) {
- if ('formulaStats' in db.DB) {
- console.warn('Changing formulaStats');
- console.log(db.DB.formulaStats[0]);
- myVue.won = parseInt(db.DB.formulaStats[0].moneyWon);
- myVue.lost = parseInt(db.DB.formulaStats[0].moneyLost);
- won = parseInt(db.DB.formulaStats[0].moneyWon);
- lost = parseInt(db.DB.formulaStats[0].moneyLost);
- myVue.ratio = (won/lost).toFixed(6);
- let formatNumber = new Intl.NumberFormat('en-US')
- db.DB.formulaStats[0].moneyWon = formatNumber.format(db.DB.formulaStats[0].moneyWon);
- db.DB.formulaStats[0].moneyLost = formatNumber.format(db.DB.formulaStats[0].moneyLost);
- myVue.formula = db.DB.formulaStats[0];
- }
- }
- Vue.nextTick(function() {
- hljs.initHighlighting.called = false;
- hljs.initHighlighting();
- });
- // Moved this to 'main' because it missed a few before
- if ('deckShuffled' in db.DB) {
- console.warn('db.DB.deckShuffled:', db.DB.deckShuffled);
- if (db.DB.deckShuffled === true) {
- deck = [];
- deck = createDeck(deck);
- }
- }
- if (status === "startGame") {
- action.lower = 0;
- action.higher = 0;
- processStartGame(db);
- }
- if (status === "gameStarted") {
- processGameStarted(db);
- }
- if (status === "makeChoice") {
- action.lower = 0;
- action.higher = 0;
- processMakeChoice(db);
- }
- if (status === "Incorrect") {
- reset();
- }
- //console.log("db.currentGame:", db.currentGame);
- }
- });
- //********
- // VIEW
- //********
- let boxTitle = "Let's play High-Low";
- let boxHTML = `<div class="tutorial-cont m-top10">
- <div class="title-gray top-round" role="heading" aria-level="5">
- <i class="tutorial-icon"></i>
- <span style="padding-left: 6px">` + boxTitle + `</span>
- </div>
- <div class="bottom-round cont-gray p10">
- <div id="app" style="min-height: 450px;">
- <div style="float: left; width: 50%;">
- <action-header v-bind:header="header"></action-header>
- <action-table v-bind:action="action"></action-table>
- <h1 style="margin: .67 em; margin-top: 10px;">Most recent formulaStats</h1>
- <formula-stats v-bind:formula="formula"></formula-stats>
- <ratio-calculation v-bind:ratio="ratio"></ratio-calculation>
- </div>
- <div id="right" style="float: right; width: 50%;">
- <!-- <pre><code class="json"></code></pre> -->
- <vue-object v-bind:jsonobject="jsonobject"></vue-object>
- </div>
- </div>
- <div class="clear"></div>
- <hr class="page-head-delimiter m-top10"
- </div>
- </div>`;
- $('.highlow-main-wrap').after(boxHTML);
- // Vue.js template
- //creating component
- var actionHeader = Vue.extend({
- template: '<h1 v-bind:style="actionStyle">{{ header }}</h1>',
- data: function() {
- return {
- // action: "Current Action",
- actionStyle: {
- marginTop: "0px"
- }
- };
- },
- props: ['header']
- });
- var vueObject = Vue.extend({
- template: '<div v-bind:style="vueObjectStyle"><pre><code class="json" v-html="jsonobject"></code></pre></div>',
- data: function() {
- return {
- vueObjectStyle: {
- marginTop: "0px"
- }
- };
- },
- props: ['jsonobject']
- });
- let templateAction = `<table class="pure-table"><caption>Odds Table</caption><thead>
- <tr><th>Action</th><th>Places</th><th>Odds</th></tr>
- </thead><tbody>
- <tr><td>Lower</td><td>{{ action.lower }}</td><td>{{ action.lower | calculatePercentage }} %</td></tr>
- <tr><td>Higher</td><td>{{ action.higher }}</td><td>{{ action.higher | calculatePercentage }} %</td></tr>
- <tr><td>Deck</td><td>{{ action.cards }}</td><td>100 %</td></tr>
- </tbody></table>`;
- var actionTable = Vue.extend({
- template: templateAction,
- filters: {
- calculatePercentage: (places) => {
- return Math.round(places * 100 / deck.length);
- }
- },
- props: ['action']
- });
- let templateRatio = "<div><h1 style=\"margin: .67 em; margin-top: 10px;\">Ratio</h1><pre><code class=\"json\" v-html=\"ratio\"></code></pre></div>";
- /* let ratioCalculation = Vue.extend({
- template: templateRatio,
- props: ['won', 'lost'],
- data: function () {
- return {
- wwon: won,
- llost: this.lost
- }
- },
- computed: {
- ratio: function() {
- console.log('[Ratio] won:', this.wwon);
- console.log('[Ratio] lost:', this.llost);
- if (this.lost === 0) {
- return '0.000000';
- } else {
- console.log('[Ratio] ratio:', (this.won/this.lost).toFixed(6));
- return (this.won/this.lost).toFixed(6);
- }
- }
- }
- }); */
- let ratioCalculation = Vue.extend({
- template: templateRatio,
- props: ['ratio']
- });
- let templateStats = '<div><pre><code class="json" v-html="formula"></code></pre></div>';
- let formulaStats = Vue.extend({
- template: templateStats,
- props: ['formula']
- });
- //registering component
- Vue.component('action-header', actionHeader);
- Vue.component('vue-object', vueObject);
- Vue.component('action-table', actionTable);
- Vue.component('formula-stats', formulaStats);
- Vue.component('ratio-calculation', ratioCalculation);
- //initializing the Vue application
- action.cards = deck.length;
- action.lower = 0;
- action.higher = 0;
- let header = "Current Action";
- let myVue = new Vue({
- el: "#app",
- data: function() {
- return {
- jsonobject: "Start",
- header: header,
- action: action,
- formula: formula,
- ratio: ratio
- };
- }
- });
- //********
- // MODEL
- //********
- /**
- * @param {array} deck, cards by number
- * @return {array} number of cards by rank where key is the rank \
- * and val is the number of that rank in the deck
- */
- let parseDeck = function(deck) {
- // Create new parsedDeck from deck
- let parsedDeck = [];
- // parsedDeck runs from 0 to 14 where 0 and 1 are always 0.
- // Real deck values count from 2 to 14 (ace)
- for (let i = 0; i <= 15; i++) {
- parsedDeck[i] = 0;
- }
- let deckLength = deck.length;
- for (let i = 0; i < deckLength; i++) {
- /*
- if (i < 10) {
- console.log('first cards:', deck[i]);
- }
- */
- let offset = 0;
- offset += 4; // Counter for 2 being first card, not 1
- offset += 3; // Counter for using floor
- let rank = Math.floor((parseInt(deck[i], 10)+offset)/4);
- parsedDeck[rank]++;
- }
- if (deckLength === 0) {
- // Shuffle -> create new deck
- for (let i = 2; i < 15; i++) {
- parsedDeck[i] = 4;
- }
- }
- return parsedDeck;
- };
- let calculateOdds = function(dealerCard, deck) {
- let parsedDeck = parseDeck(deck);
- let deckLength = parsedDeck.length;
- let numberOfCards = 0;
- let lowerDoesNotLose = 0; // Equals count as 'not lose'
- let higherDoesNotLose = 0; // Equals count as 'not lose'
- for (let i = 0; i < deckLength; i++) {
- if (i <= dealerCard.rank) {
- lowerDoesNotLose += parsedDeck[i];
- }
- if (i >= dealerCard.rank) {
- higherDoesNotLose += parsedDeck[i];
- }
- numberOfCards += parsedDeck[i];
- }
- console.assert(deck.length === numberOfCards, 'deck.length: '+deck.length+' <> numberOfCards: '+numberOfCards);
- // console.log("[calculteOdds] parsedDeck;", parsedDeck);
- action.lower = lowerDoesNotLose;
- action.higher = higherDoesNotLose;
- console.log("[calculateOdds] lowerDoesNotLose:", lowerDoesNotLose);
- console.log("[calculateOdds] higherDoesNotLose:", higherDoesNotLose);
- console.log("[calculateodds] numberOfCards:", numberOfCards);
- return [lowerDoesNotLose, higherDoesNotLose, numberOfCards];
- };
- })();
|