...
57 |
...
58 | Blog | 59 | Zone | 60 | Telegram | 61 | Github | 62 | 63 | Resume | 64 | Email
65 | How this page works 66 |
├── .gitignore ├── LICENSE ├── README.md ├── copy.js ├── head.js ├── index.html ├── screenshot.png └── title.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 idealclover 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Random Homepage 2 | ========================= 3 | 4 | A homepage based on [huzidaha-home](https://github.com/huzidaha/home). 5 | The homepage uses genetic algorithm, based on javascript. 6 | Generate a specific string from a random string. 7 | 8 | Demo preview [here](https://idealclover.top) 9 | 10 |  -------------------------------------------------------------------------------- /copy.js: -------------------------------------------------------------------------------- 1 | function copy(){ 2 | const input = document.createElement('input'); 3 | document.body.appendChild(input); 4 | input.setAttribute('value', "shadowspacex@163.com"); 5 | input.select(); 6 | document.execCommand("copy"); 7 | document.body.removeChild(input); 8 | alert("Copied to clipboard."); 9 | } 10 | -------------------------------------------------------------------------------- /head.js: -------------------------------------------------------------------------------- 1 | (function(modules) { // webpackBootstrap 2 | // The module cache 3 | var installedModules = {}; 4 | 5 | // The require function 6 | function __webpack_require__(moduleId) { 7 | 8 | // Check if module is in cache 9 | if(installedModules[moduleId]) 10 | return installedModules[moduleId].exports; 11 | 12 | // Create a new module (and put it into the cache) 13 | var module = installedModules[moduleId] = { 14 | exports: {}, 15 | id: moduleId, 16 | loaded: false 17 | }; 18 | 19 | // Execute the module function 20 | modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | 22 | // Flag the module as loaded 23 | module.loaded = true; 24 | 25 | // Return the exports of the module 26 | return module.exports; 27 | } 28 | 29 | 30 | // expose the modules object (__webpack_modules__) 31 | __webpack_require__.m = modules; 32 | 33 | // expose the module cache 34 | __webpack_require__.c = installedModules; 35 | 36 | // __webpack_public_path__ 37 | __webpack_require__.p = ""; 38 | 39 | // Load entry module and return exports 40 | return __webpack_require__(0); 41 | }) 42 | /************************************************************************/ 43 | ([ 44 | /* 0 */ 45 | /***/ function(module, exports, __webpack_require__) { 46 | 47 | 'use strict'; 48 | 49 | var _gen = __webpack_require__(1); 50 | 51 | var _gen2 = _interopRequireDefault(_gen); 52 | 53 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 54 | 55 | var isRunning = false; 56 | 57 | var init = function init() { 58 | redirectPosts(); 59 | listen(); 60 | play(); 61 | }; 62 | 63 | function redirectPosts() { 64 | var capture = window.location.search.match(/\?post=(\d+)/); 65 | var postid = capture ? capture[1] : null; 66 | if (postid) { 67 | window.location.href = 'https://github.com/livoras/blog/issues/' + postid; 68 | } 69 | } 70 | 71 | function listen() { 72 | document.getElementById('head').addEventListener('click', function () { 73 | if (isRunning) return; 74 | play(); 75 | }); 76 | } 77 | 78 | function play() { 79 | var head = document.getElementById('head'); 80 | var history = (0, _gen2.default)('Stay simple, stay naive.').history; 81 | isRunning = true; 82 | var i = 0; 83 | history.forEach(function (text, i) { 84 | setTimeout(function () { 85 | head.innerText = text; 86 | if (++i === history.length) isRunning = false; 87 | }, i * 30); 88 | }); 89 | } 90 | 91 | init(); 92 | 93 | /***/ }, 94 | /* 1 */ 95 | /***/ function(module, exports, __webpack_require__) { 96 | 97 | 'use strict'; 98 | 99 | /** 100 | * Using Genetic Algorithm to generate lots of random strings 101 | * and make them evolve towards the target string. 102 | * 103 | */ 104 | 105 | var Genea = __webpack_require__(2); 106 | var alphabetArr = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ., '.split(''); 107 | var alphabet = function () { 108 | var alphabet = {}; 109 | alphabetArr.forEach(function (ch, i) { 110 | alphabet[ch] = i; 111 | }); 112 | return alphabet; 113 | }(); 114 | 115 | function getTargetStr(targetStr) { 116 | var binaryStr = ''; 117 | for (var i = 0, len = targetStr.length; i < len; i++) { 118 | var ch = targetStr[i]; 119 | var chIndex = alphabet[ch]; 120 | binaryStr += paddingWith0(Number(chIndex).toString(2)); 121 | } 122 | return binaryStr; 123 | } 124 | 125 | function paddingWith0(num) { 126 | while (num.length < 6) { 127 | num = '0' + num; 128 | } 129 | return num; 130 | } 131 | 132 | function run(str) { 133 | var tar = getTargetStr(str); 134 | var ga = new Genea({ 135 | geneLength: tar.length, 136 | mutateProbability: 0.5, 137 | doneFitness: 1, 138 | populationSize: 20, 139 | generationsSize: 400, 140 | getFitness: function getFitness(gene) { 141 | var count = 0; 142 | for (var i = 0, len = gene.length; i < len; i++) { 143 | if (gene[i] === tar[i]) count++; 144 | } 145 | var likeness = count / tar.length; 146 | return likeness; 147 | }, 148 | onGeneration: function onGeneration(generation, genes) { 149 | var max = 0, 150 | index = 0; 151 | this.fitnesses.forEach(function (fitness, i) { 152 | if (fitness > max) { 153 | max = fitness; 154 | index = i; 155 | } 156 | }); 157 | this.history.push(toChars(genes[index])); 158 | } 159 | }); 160 | 161 | ga.history = []; 162 | ga.start(); 163 | return ga; 164 | } 165 | 166 | function toChars(gene) { 167 | var str = ''; 168 | while (gene.length) { 169 | var ch = '00' + gene.substr(0, 6); 170 | gene = gene.substr(6); 171 | var chIndex = parseInt(ch, 2); 172 | if (chIndex >= alphabetArr.length) { 173 | chIndex = Math.floor(Math.random() * (alphabetArr.length - 1)); 174 | } 175 | if (!alphabetArr[chIndex]) console.log(chIndex, parseInt(ch, 2)); 176 | str += alphabetArr[chIndex]; 177 | } 178 | return str; 179 | } 180 | 181 | module.exports = run; 182 | 183 | /***/ }, 184 | /* 2 */ 185 | /***/ function(module, exports) { 186 | 187 | 'use strict'; 188 | 189 | 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; }; }(); 190 | 191 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 192 | 193 | var Genea = function () { 194 | function Genea(config) { 195 | _classCallCheck(this, Genea); 196 | 197 | this.currentGeneration = 0; 198 | this.populations = []; 199 | this.fitnesses = []; 200 | 201 | this.mutateProbability = config.mutateProbability || 0.5; // 0 ~ 1 202 | this.generationsSize = config.generationsSize || 100; 203 | this.populationSize = config.populationSize || 100; 204 | this.doneFitness = config.doneFitness || 1; // 0 ~ 1 205 | 206 | this.geneLength = config.geneLength; 207 | this.getFitness = config.getFitness; 208 | 209 | this.outOfGenerationsSize = config.outOfGenerationsSize || this.outOfGenerationsSize; 210 | this.onGeneration = config.onGeneration || this.onGeneration; 211 | this.done = config.done || this.done; 212 | } 213 | 214 | _createClass(Genea, [{ 215 | key: "start", 216 | value: function start() { 217 | this.initPopulation(); 218 | this.makeFitnesses(); 219 | this.select(); 220 | } 221 | }, { 222 | key: "initPopulation", 223 | value: function initPopulation() { 224 | this.currentGeneration = 1; 225 | this.populations = []; 226 | for (var i = 0, len = this.populationSize; i < len; i++) { 227 | var gene = getRandomGene(this.geneLength); 228 | this.populations.push(gene); 229 | } 230 | this.onGeneration(this.currentGeneration, this.populations); 231 | } 232 | }, { 233 | key: "select", 234 | value: function select() { 235 | if (this.currentGeneration >= this.generationsSize) { 236 | return this.outOfGenerationsSize(this.populations, this.fitnesses); 237 | } 238 | var matches = this.getMatches(); 239 | if (matches.length > 0) return this.done(matches); 240 | this.generateNextGeneration(); 241 | } 242 | }, { 243 | key: "makeFitnesses", 244 | value: function makeFitnesses() { 245 | var _this = this; 246 | 247 | this.fitnesses = []; 248 | this.totalFitness = 0; 249 | this.populations.forEach(function (individual, i) { 250 | var fitness = _this.getFitness(individual, _this.populations); 251 | _this.fitnesses[i] = fitness; 252 | _this.totalFitness += fitness; 253 | }); 254 | } 255 | }, { 256 | key: "getMatches", 257 | value: function getMatches() { 258 | var _this2 = this; 259 | 260 | var bests = []; 261 | this.populations.forEach(function (individual, i) { 262 | var fitness = _this2.fitnesses[i]; 263 | if (fitness >= _this2.doneFitness) { 264 | bests.push({ 265 | gene: individual, 266 | fitness: fitness, 267 | pos: i 268 | }); 269 | } 270 | }); 271 | return bests; 272 | } 273 | }, { 274 | key: "generateNextGeneration", 275 | value: function generateNextGeneration() { 276 | this.currentGeneration++; 277 | var oldPopulations = this.populations; 278 | var newPopulations = []; 279 | for (var i = 0, len = oldPopulations.length; i < len; i++) { 280 | var father = this.rotate(); 281 | var mother = this.rotate(); 282 | var child = this.crossOver(father, mother); 283 | child = this.mutate(child); 284 | newPopulations.push(child); 285 | } 286 | this.populations = newPopulations; 287 | this.makeFitnesses(); 288 | this.onGeneration(this.currentGeneration, this.populations); 289 | this.select(); 290 | } 291 | }, { 292 | key: "crossOver", 293 | value: function crossOver(father, mother) { 294 | var pos = Math.floor(father.length * Math.random()); 295 | var child1 = father.substring(0, pos) + mother.substring(pos); 296 | var child2 = mother.substring(0, pos) + father.substring(pos); 297 | return this.getFitness(child1) > this.getFitness(child2) ? child1 : child2; 298 | } 299 | }, { 300 | key: "mutate", 301 | value: function mutate(child) { 302 | var mutateProbability = Math.random(); 303 | if (mutateProbability < this.mutateProbability) return child; 304 | var pos = Math.floor(Math.random() * this.geneLength); 305 | var arr = child.split(""); 306 | arr[pos] = +child[pos] ^ 1; 307 | return arr.join(""); 308 | } 309 | }, { 310 | key: "rotate", 311 | value: function rotate() { 312 | var pos = Math.random(); // let's roll! 313 | var soFar = 0; 314 | for (var i = 0, len = this.fitnesses.length; i < len; i++) { 315 | var fitness = this.fitnesses[i]; 316 | soFar += fitness; 317 | if (soFar / this.totalFitness >= pos) { 318 | return this.populations[i]; 319 | } 320 | } 321 | } 322 | }, { 323 | key: "done", 324 | value: function done() {} 325 | }, { 326 | key: "onGeneration", 327 | value: function onGeneration() {} 328 | }, { 329 | key: "outOfGenerationsSize", 330 | value: function outOfGenerationsSize() {} 331 | }]); 332 | 333 | return Genea; 334 | }(); 335 | 336 | function getRandomGene(len) { 337 | var gene = ""; 338 | for (var i = 0; i < len; i++) { 339 | gene += Math.floor(Math.random() * 100) % 2 === 0 ? "1" : "0"; 340 | } 341 | return gene; 342 | } 343 | 344 | module.exports = Genea; 345 | 346 | /***/ } 347 | ]); 348 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |