UNPKG

mau-mau

Version:

Card game for 2 or more players, popular in Czech Republic, Germany and other lands

1,354 lines (1,159 loc) 288 kB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ },{}],2:[function(require,module,exports){ // # Localize // is a GNU gettext-inspired (but not conformant) localization library for // Node.js var path = require('path'); var fs = require('fs'); function Localize(translations, dateFormats, defaultLocale) { // Make sure the defaultLocale is something sane, and set the locale to // its value. Also configure ``Localize`` to throw an error if missing // a translation. defaultLocale = typeof(defaultLocale) === "string" ? defaultLocale : "en"; var locale = defaultLocale; var missingTranslationThrow = true; // ## The *mergeObjs* function // is a simple helper function to create a new object based on input objects. function mergeObjs() { var outObj = {}; for(var i in arguments) { if(arguments[i] instanceof Object) { /* jshint forin: false */ for(var j in arguments[i]) { // Does not check for collisions, newer object // definitions clobber old definitions outObj[j] = arguments[i][j]; } } } return outObj; } // ## The *setLocale* function // simply sets the locale to whatever is specified at the moment, as long as it // is a string. this.setLocale = function(newLocale) { if(typeof(newLocale) === "string") { locale = newLocale; } else { throw new Error("Locale must be a string"); } }; // ## The *strings* object // contains a series of key-val pairs to be used for translating very large strings // that aren't desirable to have duplicated in several locations this.strings = {}; // ## The *getTranslations* function // is a recursive function that checks the specified directory, and all child // directories, for ``translations.json`` files, combines them into one JSON // object, and returns them. function getTranslations(currDir, translations, strings) { if(fs.existsSync(currDir)) { // Load translations.json file in current directory, if any if(fs.existsSync(path.join(currDir, "translations.json"))) { translations = mergeObjs(translations, JSON.parse(fs.readFileSync(path.join(path.resolve(currDir), "translations.json"))) ); } var pathChildren; // Load large text translations in translations subdirectory, if it exists var translationPath = path.join(currDir, "translations"); if(fs.existsSync(translationPath) && fs.statSync(translationPath).isDirectory()) { // Get all children in the translations directory pathChildren = fs.readdirSync(translationPath); // Filter out all non-default translations (the ones without a lang type) pathChildren.filter(function(child) { return !/^.*\..*\..*/.test(child); // And map these default translations into an object containing the variable name to use, // the default text, and an array of translations for this text }).map(function(child) { return { name: child.replace(/\..*$/, ""), defaultText: fs.readFileSync(path.join(translationPath, child), 'utf8'), // To make the array of translations for this default translation, filter out // all files that do not start with the primary translation filename (minus extension), with a special // case to filter out the primary translation, as well translations: pathChildren.filter(function(secondChild) { return (new RegExp("^" + child.replace(/\..*$/, ""))).test(secondChild) && child !== secondChild; // Then map this array of files into an object containing the language specified // and the translation text for this language }).map(function(secondChild) { return { lang: secondChild.replace(/\.[^\.]*$/, "").replace(/^[^\.]*\./, ""), text: fs.readFileSync(path.join(translationPath, secondChild), 'utf8') }; }) }; // For each of these long-form translation objects, add the default text to the strings object using the // desired variable name, and create a translation object for all defined languages for this text. }).forEach(function(translation) { strings[translation.name] = translation.defaultText; translations[translation.defaultText] = {}; translation.translations.forEach(function(lang) { translations[translation.defaultText][lang.lang] = lang.text; }); }); } // Recurse down each directory and get the translations for that directory pathChildren = fs.readdirSync(currDir); /* jshint forin: false */ for(var child in pathChildren) { var childPath = path.resolve(path.join(currDir, pathChildren[child])); if(fs.statSync(childPath).isDirectory()) { var tempArray = getTranslations(childPath, translations, strings); translations = tempArray[0]; strings = tempArray[1]; } } } else { throw new Error("Translation Path Invalid"); } return [translations, strings]; } // ## The *validateTranslations* function // determines whether or not the provided JSON object is in a valid // format for ``localize``. function validateTranslations(newTranslations) { if(typeof(newTranslations) !== "object") { return false; } /* jshint forin: false */ for(var translation in newTranslations) { if(typeof(translation) !== "string") { return false; } if(typeof(newTranslations[translation]) !== "object" ) { return false; } for(var lang in newTranslations[translation]) { if(typeof(lang) !== "string") { return false; } if(typeof(newTranslations[translation][lang]) !== "string") { return false; } } } return true; } // ## The *loadTranslations* function // takes a string or object, and attempts to append the specified translation // to its store of translations, either by loading all translations from the // specified directory (string), or appending the object directly. this.loadTranslations = function(newTranslations) { if(typeof(newTranslations) === "string") { var tempArray = getTranslations(newTranslations, {}, this.strings); newTranslations = tempArray[0]; this.strings = tempArray[1]; } if(validateTranslations(newTranslations)) { translations = mergeObjs(translations, newTranslations); } else { throw new Error("Must provide a valid set of translations."); } }; // Now that we have the infrastructure in place, let's verify that the // provided translations are valid. this.loadTranslations(translations); // ## The *clearTranslations* function // simply resets the translations variable to a clean slate. this.clearTranslations = function() { translations = {}; }; // ## The *getTranslations* function // simply returns the entire translations object, or returns that portion // of translations matched by the elements of a provided array of text to // translate this.getTranslations = function(textArr) { if(textArr instanceof Array) { var outObj = {}; textArr.forEach(function(text) { outObj[text] = translations[text]; }); return outObj; } else { return translations; } }; // ## The *throwOnMissingTranslation* function // lets the user decide if a missing translation should cause an Error // to be thrown. Turning it off for development and on for testing is // recommended. The function coerces whatever it receives into a bool. this.throwOnMissingTranslation = function(shouldThrow) { missingTranslationThrow = !!shouldThrow; }; // ## The *buildString* function // is a string-building function inspired by both ``sprintf`` and // [jQuery Templates](http://api.jquery.com/category/plugins/templates/) // and a small helping of RegExp. The first argument to buildString is // the source string, which has special ``$[x]`` blocks, where ``x`` is // a number from 1 to Infinity, matching the nth argument provided. // Because of ``.toString()``, string formatting _a la_ ``sprintf`` is // avoided, and the numeric identification allows the same parameter to // be used multiple times, and the parameter order need not match the // string referencing order (important for translations) function buildString() { var outString = arguments[0]; for(var i = 1; i < arguments.length; i++) { outString = outString.replace(new RegExp("\\$\\[" + i + "\\]", "g"), arguments[i]); } return outString; } // ## The *translate* function // is a thin automatic substitution wrapper around ``buildString``. In // fact, it short-circuits to ``buildString`` when ``locale`` equals // ``defaultLocale``. Otherwise, it looks up the required translated // string and executes ``buildString`` on that, instead this.translate = function() { if(locale === defaultLocale) { return buildString.apply(this, arguments); } var newText = translations[arguments[0]] && translations[arguments[0]][locale] ? translations[arguments[0]][locale] : null; if(missingTranslationThrow && typeof(newText) !== "string") { throw new Error("Could not find translation for '" + arguments[0] + "' in the " + locale + " locale"); } else if(typeof(newText) !== "string") { newText = arguments[0]; } var newArr = Array.prototype.splice.call(arguments, 1, arguments.length - 1); newArr.unshift(newText); return buildString.apply(this, newArr); }; // ## The *validateDateFormats* function // determines whether or not the provided dateFormat object conforms to // the necessary structure function validateDateFormats(dateFormats) { if(typeof(dateFormats) !== "object") { return false; } /* jshint forin: false */ for(var lang in dateFormats) { if(typeof(lang) !== "string") { return false; } if(typeof(dateFormats[lang]) !== "object") { return false; } if(!(dateFormats[lang].dayNames instanceof Array)) { return false; } if(!(dateFormats[lang].monthNames instanceof Array)) { return false; } if(typeof(dateFormats[lang].masks) !== "object") { return false; } if(typeof(dateFormats[lang].masks["default"]) !== "string") { return false; } if(dateFormats[lang].dayNames.length !== 14) { return false; } if(dateFormats[lang].monthNames.length !== 24) { return false; } for(var i = 0; i < 24; i++) { if(i < 14 && typeof(dateFormats[lang].dayNames[i]) !== "string") { return false; } if(typeof(dateFormats[lang].monthNames[i]) !== "string") { return false; } } } return true; } // ## The *loadDateFormats* function // appends the provided ``dateFormats`` object, if valid, to the current // ``dateFormats`` object. Otherwise, it throws an error. this.loadDateFormats = function(newDateFormats) { if(validateDateFormats(newDateFormats)) { dateFormats = mergeObjs(dateFormats, newDateFormats); } else { throw new Error("Invalid Date Format provided"); } }; // ## The *clearDateFormats* function // resets the ``dateFormats`` object to English dates. this.clearDateFormats = function() { dateFormats = { "en": { dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], masks: { "default": "ddd mmm dd yyyy HH:MM:ss", shortDate: "m/d/yy", mediumDate: "mmm d, yyyy", longDate: "mmmm d, yyyy", fullDate: "dddd, mmmm d, yyyy", shortTime: "h:MM TT", mediumTime: "h:MM:ss TT", longTime: "h:MM:ss TT Z", isoDate: "yyyy-mm-dd", isoTime: "HH:MM:ss", isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" } } }; }; // ## The *getDateFormats* function // returns the currently-defined ``dateFormats`` object this.getDateFormats = function() { return dateFormats; }; // Now that we have the infrastructure in place, let's validate the // optional ``dateFormats`` object if provided, or initialize it. if(validateDateFormats(dateFormats)) { this.loadDateFormats(dateFormats); } else { this.clearDateFormats(); } // The *localDate* function // provides easy-to-use date localization support. Based heavily on // [node-dateFormat](https://github.com/felixge/node-dateformat) by // Steven Levithan <stevenlevithan.com> // Scott Trenda <scott.trenda.net> // Kris Kowal <cixar.com/~kris.kowal/> // Felix Geisendörfer <debuggable.com> // MIT Licensed, as with this library. The resultant API is one where // a date string or object is the first argument, a mask string (being // either a key in the ``masks`` object or an arbitrary mask is the // second argument, and a third is a bool flag on whether local or UTC // time should be used. this.localDate = (function() { var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function (val, len) { val = String(val); len = len || 2; while (val.length < len) val = "0" + val; return val; }; // Regexes and supporting functions are cached through closure return function (date, mask, utc) { // You can't provide utc if you skip other args (use the "UTC:" mask prefix) if (arguments.length === 1 && Object.prototype.toString.call(date) === "[object String]" && !/\d/.test(date)) { mask = date; date = undefined; } date = date || new Date(); if(!(date instanceof Date)) { date = new Date(date); } if(isNaN(date)) { throw new TypeError("Invalid date"); } mask = String(dateFormats[locale].masks[mask] || mask || dateFormats[locale].masks["default"]); // Allow setting the utc argument via the mask if (mask.slice(0, 4) === "UTC:") { mask = mask.slice(4); utc = true; } var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_ + "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = { d: d, dd: pad(d), ddd: dateFormats[locale].dayNames[D], dddd: dateFormats[locale].dayNames[D + 7], m: m + 1, mm: pad(m + 1), mmm: dateFormats[locale].monthNames[m], mmmm: dateFormats[locale].monthNames[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H: H, HH: pad(H), M: M, MM: pad(M), s: s, ss: pad(s), l: pad(L, 3), L: pad(L > 99 ? Math.round(L / 10) : L), t: H < 12 ? "a" : "p", tt: H < 12 ? "am" : "pm", T: H < 12 ? "A" : "P", TT: H < 12 ? "AM" : "PM", Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 !== 10) * d % 10] }; return mask.replace(token, function ($0) { return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); }); }; })(); return this; } Localize.source = Localize.toString(); module.exports = Localize; },{"fs":1,"path":3}],3:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } // Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = exports.isAbsolute(path), trailingSlash = substr(path, -1) === '/'; // Normalize the path path = normalizeArray(filter(path.split('/'), function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.isAbsolute = function(path) { return path.charAt(0) === '/'; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(filter(paths, function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; // path.relative(from, to) // posix version exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.sep = '/'; exports.delimiter = ':'; exports.dirname = function(path) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { // No dirname whatsoever return '.'; } if (dir) { // It has a dirname, strip trailing slash dir = dir.substr(0, dir.length - 1); } return root + dir; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { return splitPath(path)[3]; }; function filter (xs, f) { if (xs.filter) return xs.filter(f); var res = []; for (var i = 0; i < xs.length; i++) { if (f(xs[i], i, xs)) res.push(xs[i]); } return res; } // String.prototype.substr - negative index don't work in IE8 var substr = 'ab'.substr(-1) === 'b' ? function (str, start, len) { return str.substr(start, len) } : function (str, start, len) { if (start < 0) start = str.length + start; return str.substr(start, len); } ; }).call(this,require('_process')) },{"_process":4}],4:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],5:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _Prompt2 = require('../engine/game/Prompt'); var _Prompt3 = _interopRequireDefault(_Prompt2); var _Ranks = require('../engine/cards/Ranks'); var _Ranks2 = _interopRequireDefault(_Ranks); var _SuitSelector = require('./SuitSelector'); var _SuitSelector2 = _interopRequireDefault(_SuitSelector); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var BrowserPrompt = function (_Prompt) { _inherits(BrowserPrompt, _Prompt); function BrowserPrompt() { _classCallCheck(this, BrowserPrompt); var _this = _possibleConstructorReturn(this, (BrowserPrompt.__proto__ || Object.getPrototypeOf(BrowserPrompt)).call(this)); _this.suitSelector = new _SuitSelector2.default(); return _this; } _createClass(BrowserPrompt, [{ key: 'attachGame', value: function attachGame(game) { _Prompt3.default.prototype.attachGame.apply(this, arguments); this.suitSelector.attachGame(game); } }, { key: 'attachPlay', value: function attachPlay(htmlHand, drawingStack) { drawingStack.addEventListener('click', drawCard.bind(this)); htmlHand.addEventListener('click', playCard.bind(this)); htmlHand.addEventListener('mousemove', selectCard.bind(this)); } }, { key: 'chooseCard', value: function chooseCard(player) { var _this2 = this; return new Promise(function (resolve, reject) { _this2.player = player; _this2.resolve = resolve; _this2.reject = reject; }); } }]); return BrowserPrompt; }(_Prompt3.default); function getParentCard(child) { while (!child.classList.contains('card')) { child = child.parentElement; } return child; } function drawCard() { if (this.player) { var reject = this.reject; this.player = this.resolve = this.reject = undefined; reject(); } } function playCard(event) { if (this.player) { var htmlCard = getParentCard(event.target), card = htmlCard.card; if (card) { var playableCards = this.game.rules.pickPlayableCards(this.player.hand); if (playableCards.indexOf(card) >= 0) { if (card.rank === _Ranks2.default.queen && this.player.hand.cardCount > 1) { this.suitSelector.chooseSuit().then(dropCard.bind(this, card, htmlCard)).catch(function (error) { console.log(error); }); } else { dropCard.call(this, card, htmlCard); } } } } } var topCardZIndex = 1; function selectCard(event) { var htmlCard = getParentCard(event.target), card = htmlCard.card; if (htmlCard.style.zIndex != topCardZIndex && card) { var availableCards = this.player.hand.pickCards(); if (availableCards.indexOf(card) >= 0) { htmlCard.style.zIndex = ++topCardZIndex; } } } function dropCard(card, htmlCard) { var resolve = this.resolve; this.player = this.resolve = this.reject = undefined; htmlCard.style.zIndex = ''; resolve(card); } exports.default = BrowserPrompt; },{"../engine/cards/Ranks":13,"../engine/game/Prompt":19,"./SuitSelector":8}],6:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Menu = function () { function Menu() { _classCallCheck(this, Menu); var templateImport = document.getElementById('template-import'), template = templateImport.import.getElementById('menu-template'), fragment = document.importNode(template.content, true); this.menu = document.getElementById('menu'); this.menu.appendChild(fragment); this.playerSelector = document.getElementById('players'); document.getElementById('new-game').addEventListener('click', function () { location.reload(); }); } _createClass(Menu, [{ key: 'attachGame', value: function attachGame(game) { this.game = game; } }]); return Menu; }(); function show() {} function hide() {} exports.default = Menu; },{}],7:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var SuitDisplay = function () { function SuitDisplay() { _classCallCheck(this, SuitDisplay); var templateImport = document.getElementById('template-import'), template = templateImport.import.getElementById('suit-display-template'), fragment = document.importNode(template.content, true); this.suitDisplay = document.getElementById('show-suit'); this.suitDisplay.appendChild(fragment); this.suitValue = document.getElementById('suit'); } _createClass(SuitDisplay, [{ key: 'attachGame', value: function attachGame(game) { this.game = game; } }, { key: 'showSuit', value: function showSuit(suit) { if (suit) { this.suitValue.textContent = suit; this.suitDisplay.style.display = ''; } else { this.suitDisplay.style.display = 'none'; } } }]); return SuitDisplay; }(); function show() {} function hide() {} exports.default = SuitDisplay; },{}],8:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _Suits = require('../engine/cards/Suits'); var _Suits2 = _interopRequireDefault(_Suits); var _EventEmitter2 = require('../engine/misc/EventEmitter'); var _EventEmitter3 = _interopRequireDefault(_EventEmitter2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var SuitSelector = function (_EventEmitter) { _inherits(SuitSelector, _EventEmitter); function SuitSelector() { _classCallCheck(this, SuitSelector); var templateImport = document.getElementById('template-import'), template = templateImport.import.getElementById('suit-selector-template'), fragment = document.importNode(template.content, true); var _this = _possibleConstructorReturn(this, (SuitSelector.__proto__ || Object.getPrototypeOf(SuitSelector)).call(this)); _this.suitSelector = document.getElementById('choose-suit'); _this.suitSelector.addEventListener('click', chooseSuit.bind(_this)); _this.suitSelector.appendChild(fragment); return _this; } _createClass(SuitSelector, [{ key: 'attachGame', value: function attachGame(game) { this.game = game; } }, { key: 'chooseSuit', value: function chooseSuit() { var _this2 = this; this.suitSelector.style.display = ''; return new Promise(function (resolve) { return _this2.resolve = resolve; }); } }]); return SuitSelector; }(_EventEmitter3.default); function show() {} function hide() {} function chooseSuit(event) { var suit = event.target.id; if (_Suits2.default[suit]) { this.suitSelector.style.display = 'none'; this.game.rules.chosenSuit = suit; this.resolve(suit); } } exports.default = SuitSelector; },{"../engine/cards/Suits":15,"../engine/misc/EventEmitter":21}],9:[function(require,module,exports){ 'use strict'; var _Ranks = require('../engine/cards/Ranks'); var _Ranks2 = _interopRequireDefault(_Ranks); var _Game = require('../engine/game/Game'); var _Game2 = _interopRequireDefault(_Game); var _Human = require('../engine/players/Human'); var _Human2 = _interopRequireDefault(_Human); var _SmartComputer = require('../engine/players/SmartComputer'); var _SmartComputer2 = _interopRequireDefault(_SmartComputer); var _Reporter = require('../engine/misc/Reporter'); var _Reporter2 = _interopRequireDefault(_Reporter); var _BrowserPrompt = require('./BrowserPrompt'); var _BrowserPrompt2 = _interopRequireDefault(_BrowserPrompt); var _SuitDisplay = require('./SuitDisplay'); var _SuitDisplay2 = _interopRequireDefault(_SuitDisplay); var _Menu = require('./Menu'); var _Menu2 = _interopRequireDefault(_Menu); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } document.addEventListener('HTMLImportsLoaded', startApplication); function startApplication() { var cardImport = document.getElementById('template-import'), cardTemplate = cardImport.import.getElementById('card-template'), drawingStack = document.querySelector('.drawing-stack'), playingStack = document.querySelector('.playing-stack'), hands = document.querySelector('.hands'), htmlCards = {}, htmlHands = {}, cardAnimations = [], playerCountValue = /[?&]playerCount=(\d+)/.exec(location.search), playerCount = playerCountValue && parseInt(playerCountValue[1], 10) || 4, players = [], dealingCards; function getHTMLHand(player) { var htmlHand = htmlHands[player]; if (!htmlHand) { htmlHand = htmlHands[player] = document.createElement('div'); htmlHand.classList.add('hand'); if (player instanceof _Human2.default) { htmlHand.classList.add('human'); prompt.attachPlay(htmlHand, drawingStack); } htmlHand.setAttribute('title', player.toString()); hands.appendChild(htmlHand); } return htmlHand; } function getHTMLCard(card) { var htmlCard = htmlCards[card]; if (!htmlCard) { var cardFragment = document.importNode(cardTemplate.content, true); htmlCard = htmlCards[card] = cardFragment.children[0]; htmlCard.classList.add(card.suit, card.rank); htmlCard.card = card; } return htmlCard; } function scheduleCardAnimation(card, player, callback) { var direction; if (player) { var availableCards = player.hand.pickCards(); direction = availableCards.indexOf(card) >= 0 ? 'to' : 'from'; } cardAnimations.push({ card: card, player: player, direction: direction, callback: callback, delay: dealingCards ? 10 : 0 }); if (cardAnimations.length === 1) { animateCard(); } } function animateCard() { var cardAnimation = cardAnimations[0], card = cardAnimation.card, htmlCard = htmlCards[card], player = cardAnimation.player; function afterInitialFlipAnimation() { htmlCard.removeEventListener('transitionend', afterInitialFlipAnimation); htmlCard.classList.add('from-pack'); htmlCard.addEventListener('transitionend', afterMoveAnimation); htmlCard.classList.add(cardAnimation.direction + '-player-' + (players.indexOf(player) + 1)); } function afterMoveAnimation() { if (player && htmlCard) { htmlCard.removeEventListener('transitionend', afterMoveAnimation); if (player instanceof _Human2.default && cardAnimation.direction == 'to') { if (htmlCard.classList.contains('flipped')) { htmlCard.addEventListener('transitionend', afterFinalFlipAnimation); htmlCard.classList.remove('flipped'); return; } } } afterFinalFlipAnimation(); } function afterFinalFlipAnimation() { if (player && htmlCard) { htmlCard.style.zIndex = ''; htmlCard.removeEventListener('transitionend', afterFinalFlipAnimation); } setTimeout(function () { if (htmlCard) { htmlCard.classList.remove('selected'); if (player) { htmlCard.classList.remove('from-pack', 'from-player-1', 'from-player-2', 'from-player-3', 'from-player-4', 'to-player-1', 'to-player-2', 'to-player-3', 'to-player-4'); } } cardAnimation.callback.call(this, card); cardAnimations.shift(); if (cardAnimations.length) { setTimeout(animateCard, 0); } }, cardAnimation.delay); } if (player && htmlCard) { htmlCard.style.zIndex = 100; var method = cardAnimation.direction == 'to' ? 'add' : 'remove', flipped = htmlCard.classList.contains('flipped'); if (flipped && method === 'remove' || !flipped && method === 'add') { htmlCard.addEventListener('transitionend', afterInitialFlipAnimation); htmlCard.classList[method]('flipped'); } else { afterInitialFlipAnimation(); } return; } if (htmlCard) { htmlCard.classList.add('selected'); } afterMoveAnimation(); } players.push(new _Human2.default()); while (--playerCount) { players.push(new _SmartComputer2.default()); } var prompt = new _BrowserPrompt2.default(), game = new _Game2.default({ players: players, prompt: prompt }), suitDisplay = new _SuitDisplay2.default(), menu = new _Menu2.default(); suitDisplay.attachGame(game); menu.attachGame(game); game.on('game:starting', function () { dealingCards = true; // Initial card dealing and turning over the playing stack game.drawingStack.on('cards:received', function (cards) { // The first card (the top card) has to be the last element added, // so that it gets naturally to the top without z-index cards.reverse().forEach(function (card) { scheduleCardAnimation(card, undefined, function () { var htmlCard = getHTMLCard(card); htmlCard.classList.add('flipped'); drawingStack.appendChild(htmlCard); }); }); }); // Playing a card game.playingStack.on('cards:received', function (cards) { if (dealingCards) { cards.forEach(function (card) { scheduleCardAnimation(card, undefined, function () { var htmlCard = getHTMLCard(card); htmlCard.classList.remove('flipped'); playingStack.appendChild(htmlCard); }); }); } }); // Drawing a card game.players.forEach(function (player, index) { player.on('player:drawn', function (card) { scheduleCardAnimation(card, !dealingCards && player, function () { var htmlCard = getHTMLCard(card), htmlHand = getHTMLHand(player), method = player instanceof _Human2.default ? 'remove' : 'add'; htmlCard.classList[method]('flipped'); htmlHand.appendChild(htmlCard); }); }).on('player:played', function (card) { scheduleCardAnimation(card, player, function () { var htmlCard = getHTMLCard(card); htmlCard.classList.remove('flipped', 'selected'); playingStack.appendChild(htmlCard); }); var suit = game.playingStack.peekAtTopCard().rank === _Ranks2.default.queen && game.rules.chosenSuit; suitDisplay.showSuit(!game.rules.whoWins() && suit); }); }); }); game.on('game:started', function () { dealingCards = false; }); game.on('game:turning-over', function () { dealingCards = true; }); game.on('game:turned-over', function () { dealingCards = false; }); game.start(); } },{"../engine/cards/Ranks":13,"../engine/game/Game":17,"../engi