{"_id":"@articulatesydney/gmservice","_rev":"4-5ac80634caaddef5f3acc8b77d2e9380","name":"@articulatesydney/gmservice","dist-tags":{"latest":"2.1.1"},"versions":{"1.0.0":{"name":"@articulatesydney/gmservice","version":"1.0.0","_id":"@articulatesydney/gmservice@1.0.0","_npmVersion":"6.4.1","_nodeVersion":"8.1.4","_npmUser":{"name":"francox","email":"sunxufei92@gmail.com"},"dist":{"integrity":"sha512-d08tr3euru6xQcwnF3/WzBS3RyQ63S/9UaToc81kH5E71//gvgIHwG8p0iW+LFLT4Gl+SuENeittQ3M002IYnQ==","shasum":"8180612bed92424f2380ffa8411ad18084c64b6d","tarball":"https://registry.npmjs.org/@articulatesydney/gmservice/-/gmservice-1.0.0.tgz","fileCount":1,"unpackedSize":62,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqOBuCRA9TVsSAnZWagAAv2EP/RZIVCHWD26qRvcrk5aZ\nfi5a3YP0jS8el36HjClcH7pK7pIALRTvppfUUA7Mek7VoQIScJjTal4FUCkp\n8XOJ4TkBTe49cehlSXf7ARTuKph2HHQic9zKGoZqzSin6L2BEjfWm7hUNR+B\ndFuRBYSjN1P/p1QoTcsOn7M94zU3fPee42SxuFWT2l+mKlS0q1bzgQ6z6ftE\n7MoHiBm/7GyzMJ7Bd7Y9ByUvD/MmqmwOBmrHUcHsavvPNL1cVSqW196pgHJt\n3D0wZ2uzH0vbJYhKbL2Im7QOJTzUHOGV5Wc338Q/Tvh1+W9h8a2z6flm9QSi\neFOo2891hhZAx1syuxpuJT0sxX3yNKCqdmTtWy5MLODLv/NlmFTNrgKHyw69\n5Fm+zRMXCM20qMGNBYfFa8F6kAN7VCVl0m9iXJbsDFahF31pWL6mkCWVs24x\nemqgO3uKwzsmUXEtV0CgmgxtGYO19AUKaq0HpEWRo9/bUmzwgkK22p1q9jMJ\nYOZqAItrpUKAevYdPfyor6RSdd66RH8ZmqLBUYYXVzi7ygAz0Lk4Hay3EKvb\nG3GmTpXNB+ubs7Ghe+n5UhHdCyT6cDO16L7dq3UMYGoig+G/Ns5Luv1Z9p7A\nY1gbyPLsjkHXHDtVn/4slATirn4oHA0J+/UXKRO/THFCcx2XLxeFiYEmyXM4\nwngt\r\n=+3+L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7Jubg70CNQC8fp1JES+9ngYv0DrzbCKsvCfAZGcjRrAiEAmLpcCRghJS7z0TOGuROxsvHZdLJzdY3pubWIo5gfYno="}]},"maintainers":[{"name":"francox","email":"sunxufei92@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/gmservice_1.0.0_1537794158041_0.8097278873281395"},"_hasShrinkwrap":false},"2.0.0":{"name":"@articulatesydney/gmservice","version":"2.0.0","main":"index.js","dependencies":{"is-mobile":"^2.0.0","rx-lite":"^4.0.8"},"devDependencies":{"babel-cli":"^6.26.0","babel-preset-env":"^1.7.0","jest":"^23.6.0","rollup-plugin-node-resolve":"^3.4.0"},"scripts":{"test":"npx jest","build":"rollup -c --production"},"gitHead":"2bb93ea30b3a7838190e350abe9650d3a47e5392","description":"GM-SERVICE ====","_id":"@articulatesydney/gmservice@2.0.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"francox","email":"sunxufei92@gmail.com"},"dist":{"integrity":"sha512-hPzZe+bLfVyRq6R8P+mIh/Wgg/lvmP+WdDOBI88FrOkWK2Fh5y3twisS6Ozo0mmJjByVKafqd+VaXI6D5Vhjqg==","shasum":"da65a6636a0f0f1403379981afb3ac88ccbe843d","tarball":"https://registry.npmjs.org/@articulatesydney/gmservice/-/gmservice-2.0.0.tgz","fileCount":38,"unpackedSize":662770,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbyWGrCRA9TVsSAnZWagAAabkP/jVYuR6WUxVmJebhBwNg\nil/+FrsO7KRdMpIMFqrQblz0GWeMjfDFl/1iPfShbH9YgTxiVlGyuCXKRLFW\nHQhZ9So6Tj9BUR+5ML6UeIH7+aeDTi5j8bH00YQk1w+dk01vk4hj4u5qIiKt\ntWzi2U6wpn2zFKjE9Nq306A4Zo9OXsaAyOnk7kWWLA3E6luNswDB7jqFdF2w\nBfpcLYZDF7JM5hNYOb2+z/XcfDDhNwjy7mgNY/pY7VkbSFeQpZWyGED2JLgj\nvb7XzGtITaSlnCG7LwJC+fIZs3KJc6cnAPI1q8ZxMX7c+Fe87TaLPA1dsrcB\nMl3FDC0A5cGXJ0XhJgh5iXdl79uX7b02oH4xQcCT2fxCd1ZyV6/0aX0HYQaf\nF8KICWXff4Ef75TRZPt8YTaULTWUhtCTbtCuzAo71pohsm83XI7a3E0ZPtcf\nZDDaAZuS/KgsWaPFFNSk0XN0rcQnfDI5TrLoESaos9Xs+Xx4mdJm0K7OT4iD\nbNNVQ7Vl3Ms24AF7+H2d3dC+VWXfqjzr/fb3XfUm6gc0upVrIbZaN95XT5VK\nKvSwhZck0c7Mt/UAx4CvtAou9OM4ZSkJAknne9JUxdxvN8PM9buOyR6CRZ7B\nipMfBanm+cOdeuy9CVQXX1ZF10b12meokSIQFmthaJfNyhw0DW/LpWXDTgRQ\n5Pxv\r\n=NC6G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPguGhk6fi+iW6nUOKSIO5ugG8zmc0snPMtuAvCeTuZQIgRvN7zLbwZIGif38xl2mDtJtlP+9OViNMLNwXxOg605E="}]},"maintainers":[{"name":"francox","email":"sunxufei92@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/gmservice_2.0.0_1539924394582_0.43731655177207873"},"_hasShrinkwrap":false},"2.1.0":{"name":"@articulatesydney/gmservice","version":"2.1.0","main":"index.js","dependencies":{"is-mobile":"^2.0.0","rx-lite":"^4.0.8"},"devDependencies":{"babel-cli":"^6.26.0","babel-preset-env":"^1.7.0","jest":"^23.6.0","rollup-plugin-node-resolve":"^3.4.0"},"scripts":{"test":"npx jest","build":"rollup -c --production"},"gitHead":"76b412eb77a4dce9cbe163ca9ddde9bd5e0a3756","description":"GM-SERVICE ====","_id":"@articulatesydney/gmservice@2.1.0","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"francox","email":"sunxufei92@gmail.com"},"dist":{"integrity":"sha512-bxrXGjoZIN2rDuhxlTYxwFKhZul8j9DhhB5XeqyrpVdsVaK84zl9O73FYTraXMeJE6NC5iF22HIFlbCG/wOIPg==","shasum":"a74d64345b10a69998d01b005b598c306ed485a6","tarball":"https://registry.npmjs.org/@articulatesydney/gmservice/-/gmservice-2.1.0.tgz","fileCount":38,"unpackedSize":669749,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbz+vNCRA9TVsSAnZWagAA9X0QAJEqLZR13z6UgElJk/I3\nLQ/v6SPT4asrPx93cLSHRvv7Oi+kofjasUjGpstT9b4oISvm1YQICwUzwSqb\nDVkxuqa73wpiZxwFrE9N1pzud8uaAQbbki/z+DAsZtxOt8S/SUzTce3JHPfQ\nsjEreDA7/CpOXIHHWw9Kkzyb4h3dpF+sP6OG+JuMxG5jyr/4Su1XEnj04/dq\ndH2Je1It5vtVxlQoYH1qrGmwjZn4GvcdcnqE7rnEXhMO0fbo57Pt6NpiO2Bq\nFPbsJe4A/Xtzuu/zrstl2XYYEs7RxGEq/revoTtiUXWFcrosXi6nE9QCyIKN\n+WVyFrR2g4S88TLF9emjo3HS2DE6lRwFsJiGkB9rff95JKUAzdOLA3Hryj9g\nN0kvUKVh7uGpsBxuVJf8sfU+myo25KjaZZ8YYFXK9E6bG1BG4cyKUOrldyBX\nqhxfqS6jjuzeBIZ1nDyL2U3I289uDlD9xPlJqpdye9dUVIPExNMVYn8e+CRv\nPnjqi70CsmOX7jzzpW9BltIx23Sk7ge9IjKCKfBpgT06hJavtRXyuOW5xfgL\nrsIHMQBqYNbeVFgdHP8EcFycfPBUOyc2dBjvnvKJrj3b2Lqs5Z0Ypkihr4O+\nmsBJfupSbsq1zA77VZsstiITfEQ28WiiOuejU5vYRULn83Oxhx/Pm1jv/Ks8\nA76c\r\n=PFiN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAC7ONUls1I1w0XHKSYnfBrSlWtyP+3TwNJBrpvyGMLCAiAFaKwHw+BB8l3I5BuoHETJKMQlK5FKHZvAftLnlrMXiA=="}]},"maintainers":[{"name":"francox","email":"sunxufei92@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/gmservice_2.1.0_1540352972945_0.5859162748404687"},"_hasShrinkwrap":false},"2.1.1":{"name":"@articulatesydney/gmservice","version":"2.1.1","main":"index.js","dependencies":{"is-mobile":"^2.0.0","rx-lite":"^4.0.8"},"devDependencies":{"babel-cli":"^6.26.0","babel-preset-env":"^1.7.0","jest":"^23.6.0","rollup-plugin-node-resolve":"^3.4.0"},"scripts":{"test":"npx jest","build":"rollup -c"},"gitHead":"a3c6dc403df30b197e0fb427ee7ccb0cf17fea93","description":"GM-SERVICE ====","_id":"@articulatesydney/gmservice@2.1.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"francox","email":"sunxufei92@gmail.com"},"dist":{"integrity":"sha512-GHM3ULtgJKK7kUmB0gTXhRIMJ2JoCySjcnSuwRh5tQ8kwq4UNqefgYvxRZbJR6npkJrTFeNVkN/sRFg1wDXj5A==","shasum":"330dea5d4adb08e1ae83f997e683fe8d86cb3b12","tarball":"https://registry.npmjs.org/@articulatesydney/gmservice/-/gmservice-2.1.1.tgz","fileCount":38,"unpackedSize":680022,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb8zuLCRA9TVsSAnZWagAAGpwQAIPbPVr7oomrrZM1H3sk\nx3koOsx2mCStV3D+AI/aDHK3siK+p9t6uE6l8Sw3fKJUpE/dBmmyq2P8U3zW\n9emkQBArjxNYijBeD3mM3rlV2S4ShWJCBD8YSooZGOG+1GMR/rHOKCe5AsZx\nA+Y8L3CKmE4sIfuQx/LfnVqKCzYP+o4IYcYKCxhaqplJDWXthzpc8kNOA13I\nd6sLm+L12H8O/tgKYpUZ9YZEd4UVYzCRA84zemaNnz8j2Z2jFQlIHporfsNN\nyE09QF83/o6vrK8RjnT6V2Wfb8uFDc86Ep4bSZoQ3hO6RgNDQASfxaDt0XLo\nkVjAEVX7CBlfVVelTdpoeYZWJh5lp+LGCFT7o5wJYTqosBU5CljHwMcax2Ds\nHDWjMfXh4lsFm9hfxaGRw9KXgHJ4pVHqY5Lxx/tuCu1Gq8RaFawSjr6lMmLL\nWLwqd6CICnI27QGBuIzp+Xlz8KF3RyalCV8Q4tYzD5nUrc1y4xAwq3rveVSX\niJ096xm8uBpLoOfqcPQrXQVH3qboKA/nisBNEIArS/Dek52lTn5pIOep6pV2\npqSdFI7mwpF24WQkBxHpdGPEDcKlUr+lJU9dWnzhuKMNAnYFc0LE4Rfyf8r4\nVmInTuqMJtxNE8sCDyGiWbzpkqcUqT86RVE0SsBZH2farMQubqliPpfdt0b+\njYxH\r\n=cBFt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCTj5IGTAdOjLfKFSI9f8omZrRT0t2aNOKpq41Aci+gqwIhAP9wU3tYR4FK3tqmanX/OYpxM+dCSjW+ru7Q6z3/3OJ0"}]},"maintainers":[{"name":"francox","email":"sunxufei92@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/gmservice_2.1.1_1542667146677_0.7122725179566562"},"_hasShrinkwrap":false}},"time":{"created":"2018-09-24T13:02:37.867Z","1.0.0":"2018-09-24T13:02:38.129Z","modified":"2022-04-04T15:38:34.359Z","2.0.0":"2018-10-19T04:46:34.763Z","2.1.0":"2018-10-24T03:49:33.092Z","2.1.1":"2018-11-19T22:39:06.821Z"},"maintainers":[{"name":"francox","email":"sunxufei92@gmail.com"}],"readme":"GM-SERVICE\n====\n\n# About\n本JS库目的在于管理游戏列表 主要特性有\n1. 提供常用的异步数据支持\n2. 封装常用的展示游戏列表的方式\n3. 基于rxjs 非常extendable\n\nGMService基于rxjs，数据交互操作全部为异步实现。 获取数据的接口的使用方式基本上都是\n```javascript\ninstance.someapi.subscribe(data => {\n    //...\n})\n```\n[完整API列表]()\n\n\n# 如何使用\n\n## 安装\n```\nnpm install --save @articulatesydney/gmservice\n```\n或者直接在html中加入\n```\n <script src=\"....bundle.js\"></script>\n```\n\n## 测试\n```\nnpm run test\n```\n\n## Build\n```\nnpm run build\n```\n\n## 使用\n1. 设置参数并初始化gmservice 得到gmservice的instance\n```javascript\nvar instance = new gmservice({\n    games: GAMELISR,\n    cache: 10000,\n    launchGame: function (game, { resolve }) {\n        // ... resolve(xxxx)\n    }\n})\n```\n\n2. 从instance提供的api中获取数据\n\n 获取provider\n```javascript\ninstance.providers.subscribe(providers => {\n    console.log(providers);\n})\n```\n\n 获取完整游戏列表\n```javascript\ninstance.list(games => {\n    console.log(games);\n})\n```\n\n## Tips\n1. 请避免使用fat arrow functions(transform函数以及process函数除外)\n2. 在gallery中使用transform.order的时候, GALLERY_FORMAT.PROVIDERS_OF_CATEGORIES模式中将会先调用category的order方法；对于每个category内部的providers的顺序会由groups order决定（example请见测试用例以及example lobby.html）\n\n# Configuration\n\ngmservice内部默认认为传入的游戏列表为标准格式,\n可以在games中直接传入标准格式的游戏列表；也可以使用rawProcess函数进行\n\n标准格式包含以下property\n\n1. cn_name: string\n2. en_name: string\n3. image: string\n4. code: string\n5. provider: string\n6. category:string\n7. types: object - 这个设计是为了实现一个游戏可以同时有多个类型的需求\n```javascript\n{\n    slot: true,\n    jackpot: true,\n    asian: true\n}\n```\n8. extra: object - \b用于记录额外的数据：可能在自定义的搜索中使用\n\n\n## 配置列表\n\n\n```javascript\nvar instance = new gmservice({\n    \n    /**\n    * 1. games\n    * - 如果网页版\b游戏列表与h5有出入, 具体如何加载合适的游戏列表需要使用者自己处理\n    * \n    * format: \n    *  - array of games OR\n    *  - function\n    *    主要用于异步加载游戏列表：在load完成后调用resolve\n    *  \n    */\n    games: gamelist,\n    games: (resolve) => {\n        fetch('/gamelist')\n        .then(d => d.json())\n        .then(games => {\n            resolve(games)\n        })\n\n        /*\n        games: (resolve) => resolve(gamelist)\n        与\n        games: gamelist\n        等价\n        */\n    }\n\n    /**\n     * 2. providers \n     * - 在游戏列表上筛选特定平台的游戏\n     * - 主要用于在cache了完整的游戏列表的环境中 只向玩家显示特定平台的相关游戏数据\n     * \n     * **如果游戏列表中本来就没有给定平台的游戏 也不会造成多余的显示\n     * \n     * providers format\n     * - array of provider names\n     * - function\n     * \n    */\n    providers: ['PNG', 'MG']\n    providers: (resolve) => {\n        fetch('/valid_providers')\n        .then(d => d.json())\n        .then(providers => resolve(providers));\n    },\n\n    /**\n     * 3. categories\n     * - 在游戏列表上筛选特定类型的游戏\n     * - 主要用于在cache了完整的游戏列表的环境中 只向玩家显示特定类型的相关游戏数据\n     * \n     * **如果游戏列表中本来就没有给定平台的游戏 也不会造成多余的显示\n     * \n     * categories format\n     * - array of provider names\n     * - function\n     * \n    */\n    categories: ['slots', 'live']\n    categories: (resolve) => {\n        fetch('/valid_categories')\n        .then(d => d.json())\n        .then(categories => resolve(categories));\n    },\n\n    /**\n     * 4. filter - function\n     * - 在游戏列表上自定义筛选游戏\n     * - 主要用于根据特殊条件过滤游戏： \b比如说 不希望玩家看到 rtp超过95%的游戏；\n     * 或者不希望玩家看到PNG的带有slot字样的游戏\n     * \n     * filter format\n     * - function\n     * \n    */\n    filter: (game) => {\n        return game.extra.rtp < 0.95;\n        // return game.provider !== 'PNG' || game.en_name.search('slots') < 0\n    }\n\n    /**\n     * 5. rawProcess - function\n     * - 用于对\b游戏列表进行预处理 以转换至标准格式\n     * \n    */\n    rawProcess: function (g) {\n        return Object.assign(g, {\n            code: g.game_code,\n            cn_name: g.name,\n            en_name: g.english_name,\n            types: (g.game_type || '').split('_').reduce((prev, t) => ({ ...prev, [t]: true }), {}),\n            extra: {}\n        })\n    },\n\n    /**\n     * 6. injectUpdates - function\n     * \n     * function injectUpdates({gamelist, cache_updated_at, cache_expire_at}, resolveFn): void\n     * \n     * - \b检查游戏列表是否有更新：如果有的话将新的数据纳入系统\n     * - 新的数据不会被rawProcess处理（因为可能还有updated/removed games的情况，injectUpdates用来处理一些非常灵活的情形）\n     * - 如果同时还开启了cache 新的数据\b\b以及当前的timestamp将被写入cache；做为下次调用时的cache_updated_at\n     * \n     * - 一个特别的使用例子：在lobby上使用时 推荐cache设置为999999999: 即使有cache也会检查更新，而且更新的timestamp会被写在cache中\n     * \n    */\n    injectUpdates: ({gamelist, cache_updated_at, cache_expire_at}, resolve) => {\n\n        fetch(`/new_games?updated_at=${cache_updated_at}`)\n        .then(d => d.json())\n        .then((newgames = []) => {\n            resolve([...gamelist, newgames]);\n        })\n    },\n\n\n    /**\n     * 7. cache - \n     * - 保存处理完成之后的游戏列表\n     * - 如果有合法的cached游戏列表存在的话 将不会使用games参数传入的游戏列表或者function\n     * - 网页版与h5版的游戏列表将分别cache\n     * - \n     * \n     * format：\n     *  - number - 浏览器中使用localStorage: \b在浏览器中保存\n     *  - \bstring: 'session' - 浏览器中使用 sessionStorage： 本次tab session中cache游戏列表\n     * \n    */\n    cache: 1000 * 60 * 60 * 24 * 7, // 1 week\n    cache: 'session',\n\n\n    /**\n     * 8. recommends: \n     * - \b接受的数据为一个array：将\bindex=0的数据\b视为全局推荐游戏列表\n     *  index=1的数据视为\b对应agent的推荐游戏列表\n     * - 为了解决inconsistancy 推荐游戏列表实际上提供一些标准 还是会从gamelist中去匹配合适的数据；每个object只需要但必须要提供provider,category以及code\n     * \n     * format：\n     *  - array of gamelist arrays [gamelist1, gamelist2]\n     *  - \bfunction\n     * \n    */\n   recommends: [general_recommends, operator_recommends],\n   recommends: (resolve) => {\n       fetch('/some-recommends?playerid=111')\n       .then(d => d.json())\n       .then(data => resolve(data))\n   },\n\n   /**\n     * 9. recommendProcess - function\n     * - 类似于 rawProcess: 将推荐游戏列表的数据处理成标准状态\n     * \n    */\n   recommendProcess: function (g) {\n        return ({\n            category: g.category,\n            provider: g.provider,\n            code: g.code,\n            extra: {\n                priority: g.priority,\n            }\n        });\n    },\n\n    /**\n     * 10. recommendStrategy - function\n     * - \b接受一个第一个元素为全局推荐游戏列表、第二个元素为agent推荐游戏列表的array为参数\n     * - 返回一个推荐游戏array\n     * - strategy将在 recommendProcess之前调用：数据尚未被处理\n     * - \b默认stategy为 general.concat(operator); 主要使用方式包括 将operator推荐游戏前置 或者将某一类型的\b推荐游戏前置\n     * \n    */\n   recommendStrategy: ([general, operator]) => \n        general.filter(g => g.provider == 'PNG').concat(operator)\n\n    /**\n     * 11. launchGame - function\n     * - 打开游戏请求的处理函数\n     * - 在instance上使用getLaunchUrl时触发\n     *   resolve and launchGame get success status and data\n     *   reject and  launchGame get error status and data\n     * \n    **/\n    launchGame: (game, { resolve, reject }) => {\n        const {provider, code} = game;\n        \bfetch(`/open-game?provider=${provider}&code=${code}`)\n        .then(response => {\n            if (provider == 'PNG') resolve('....' + response);\n            else resolve(response);\n        })\n        .catch(error => {\n            reject(error);\n        })\n    },\n\n    /**\n     * 12. getBalance - function\n     * - 获取平台余额的处理函数\n     * - 在instance上使用 getBalance 时触发\n     *   resolve and getBalance get success status and data\n     *   reject and  getBalance get error status and data\n     * \n    **/\n    getBalance: (provider, { resolve, reject }) => {\n        \bfetch(`/get——balance?provider=${provider}`)\n        .then(balance => {\n            resolve(balance);\n        })\n        .catch(error => {\n            reject(error);\n        })\n    },\n\n    /**\n     * 12. transform\n     * \n     * format: {order: fn, rename:fn}\n     * \n     * - transform主要是用于\n     * - transform会在gmservice即将输出的时候\b\b执行，不会对内容数据产生影响：因此可以配合config使用、即时更新输出数据\n     * - 主要的使用方式： 更改名字、改变order，以及在切换语言的时候即时更新所有受影响的部分\n     * \n     * - order: function (groups, providers, categories, types):void\n     *   会在原有的object上操作 所有需要使用 .sort/.splice 之类的function\n     * \n     * - rename: function(keyword, type)\n     *   rename如果没有明确返回值 则使用原本的value\n     *   rename type分为了三类 provider, category 以及type\n    **/\n\n   /*\n    const cateOrder = {\n                'sports': 1,\n                'live': 2,\n                'slots': 3,\n                'sports': 4\n    }\n   */\n\n    transform: {\n        rename: function(key, type) {\n            if (type == TYPES.GAMETYPE) return ({\n                        roulette: \"百家乐\",\n                        slots: '老虎机',\n                        probability: '概率',\n                        tablegame: '桌游',\n                        videopoker: '扑克游戏',\n                        'video-bingo': \"宾果\"\n                    })[key];\n            if (type == TYPES.CATEGORY) return ({\n                slots: '电子游戏'\n            })[key];\n        },\n        order: function(groups, providers, categories, types) {\n            if (categories) categories.sort((cateA, cateB) => {\n                return cateOrder[cateA] - cateOrder[cateB]\n            })\n        }\n    },\n\n\n\n})\n```\n\n\n# API \n\n- __group: provider + category__ 比如说 [PNG slots] [MG slots] [MG live]是三个不同的group\n\n- __active group__ 任何时候都会存在一个provider+category的\b组合作为active group；默认值为  ```{provider: null, category: null} ```.  gamelist, types, recommend等数据都会受当前active group影响\n    - \b同时存在provider与category\n    - 只有provider - 显示provider下所有category的数据\n    - 只有category - 显示category下所有provider的数据\n    - 都没有 - 显示全局数据\n\n- __filters__ gameStream emit的是active group中的游戏列表, filterStream emit的是gameStream\u001b \b\b的数据经过\b筛选后的结果. 筛选的filter有三种\n    - keyword: 游戏名称\n    - type: 游戏类型\n    - limitTo: 最大显示游戏数 \n\n- __stream__ stream即rxjs中的observable: 在api中主要操作方式为 .subscribe ; \b所有以stream结尾命名的api都会多次emit数据：只需要subscribe一次； 如果只想获取一次数据可以使用 take(1) 比如 ```instance.typeStream.take(1).subscribe(types => {/*....*/})```\n\n|#| API | 功能 | 示例 |\n|-|-|-|-|\n1 |recommends(groupObject) | 根据provider + category获取推荐游戏列表 | ```instance.recommends({provider: 'PNG', category: 'live'})```<br>```.subscribe(games => {/* .... */})``` |\n2 |recommendStream | 当前active group的推荐游戏列表 | ```instance.recommendStream```<br>```.subscribe(games => {/* .... */})``` |\n3|list | 完整游戏列表 | ```instance.list(games => {/* do something */})``` |\n4|setGroup | 设置active的group | ```instance.setGroup({provider:'PNG', category: 'slots'}})``` <br><br> ```instance.setGroup({provider:'Betsoft'})``` |\n5|setFilter(filters, reset) <br> <br> (limitTo默认为20) <br> reset如果为true 则会将filters先reset再加上传入的filters; 如果为false，则只会\b更新传入的filter，未传入的部分不变 | \b更新Filter | ```instance.setFilter({keyword: '\bdiamond'})```<br>```instance.setFilter({ type:'slot' })```<br>```instance.setFilter({ limitTo: 50})```<br>```instance.setFilter({}, true)``` |\n6|loadMore(howmany?) <br> 默认额外加载20个游戏 | 加载更多游戏(更新filter) | ```instance.loadMore()``` <br> ```instance.loadMore(30)``` |\n7|gameStream | 当前active group对应游戏列表 | \b\b```instance.gameStream``` <br> ```.subscribe(games => {/* do something */})```|\n8|filteredStream | filter之后的当前active group对应游戏列表 | ```instance.filteredStream``` <br> ```.subscribe(games => {/* do something */})``` |\n9|gameGroupStream （相同于gameStream+typeStream）| active group的数据 | |\n10|typeStream <br> (注意！只有当\bactive group同时设置了provider与category, typeStream才会有数据) | 当前active group对应类型列表 | ```instance.typeStream``` <br> ```.subscribe(types => {/* do something */})``` |\n11|activeGroup | 当前active的group | ```instance.activeGroup``` <br> ```.subscribe(group => {/* do something */})``` |\n12|getLaunchUrl | 打开游戏 | ```api.getLaunchUrl({ provider: 'PNG', code: 1000 })``` <br> ```.subscribe(data => { data.status == 'success' && window.open(data.data) || alert(data.data) ``` |\n13|getBalance | 获取平台余额 | ```api.getBalance('PNG')``` <br> ```.subscribe(data => { data.status == 'success' && alert('balance=' + data.data) || alert(data.data) ``` |\n14|providers <br> (\b会被transform影响)| \b平台列表 | ```instance.providers``` <br> ```.subscribe(providers => {/* do something */})``` |\n15|balances <br> 会在getBalance请求完成时更新(注意: 进入或退出loading的状态不会造成balances的emit) | 平台余额Map | ```instance.balances``` <br> ```.subscribe(balances => {/* do something */})``` |\n16|categories <br> (\b会被transform影响)| 类型列表 | ```instance.categories``` <br> ```.subscribe(categories => {/* do something */})``` |\n17|groups <br> (\b会被transform影响)| group列表 | ```instance.groups``` <br> ```.subscribe(groups => {/* do something */})``` |\n18|indicators <br> 两个\bsubscribable的indicator: moreToLoad (boolean) , loading (array of targets in loading state) | \b当前数据状态的指示 | ```indicators.moreToLoad``` <br> ```.subscribe(moreToLoad => moreToLoad && show(loadMore\bButton)\b; })```<br><br>  ```indicators.loading``` <br> ```.subscribe(states => { app.ready = states.length === 0 })``` |\n19|gallery<br>(会被transform影响)| 按照一定格式获取全部或者部分数据 | ```instance.gallery({}, GALLERY_FORMAT.PROVIDERS_OF_CATEGORIES).subscribe(games => {...})``` <br> ```instance.gallery({provider:'PNG'}).subscribe(games => {...})``` |\n20|config | 重新设置rename/order函数; 操作之后各个stream将会重新计算并emit 因此可以支持语言切换 | ```api.config({transform: {rename: fn}})```|\n            \n                \n\n\nLoading State 列表\n- LOADING_GAMELIST\n- LOADING_PROVIDERS\n- LOADING_CATEGORIES\n- LOADING_RECOMMENDS\n\nGALLERY_FORMAT 列表\n- CATEGORIES_OF_PROVIDERS\n- PROVIDERS_OF_CATEGORIES\n\nTYPES 列表\n- PROVIDER\n- GAMETYPE\n- CATEGORY","readmeFilename":"README.md","description":"GM-SERVICE ===="}