Hash unique ID generator
forked from forked from: Unique id generator (diff: 423)
http://hashids.org/ Converted somewhat to Haxe, exported out to AS3 code. https://github.com/Glidias/Asharena/blob/master/src/util/ds/HashIds.hx
ActionScript3 source code
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zJrB
*/
// forked from Glidias's forked from: Unique id generator
// forked from Glidias's String-based auto-number generator
package {
import flash.display.Sprite;
import com.bit101.components.*;
import flash.events.Event;
public class FlashTest extends Sprite {
private var labeler:Label;
private var labeler2:Label;
private var numStepper:NumericStepper;
private var hashIds:HashIds;
private var txtBox:TextArea;
public function FlashTest() {
// write as3 code here..
hashIds = new HashIds("this ain't worth my salt", 6, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
var vBox:VBox;
addChild( vBox = new VBox() );
numStepper = new NumericStepper(vBox);
numStepper.minimum = 0;
numStepper.maximum = int.MAX_VALUE;
numStepper.width = 200;
labeler = new Label(vBox);
labeler2 = new Label(vBox);
numStepper.addEventListener(Event.CHANGE, numStepperChange2);
txtBox = new TextArea(vBox);
scaleX = 2;
scaleY = 2;
}
public function encodeNewId(count:int):String {
var date:Date = new Date();
var sId:int = 1;
var val:Number = int( sId + "" + padd( date.getDate() ) + padd( date.getMonth() + 1 ) + ( date.getFullYear() - 2000) );
var valInt:Number = int(val);
if (val != valInt) throw new Error("Mismatch integer");
return hashIds.encode( [ count, val ] );
}
private function padd(val:int):String {
return (val < 10 ? "0" : "") + val;
}
private function getYear(val:int):String {
return val.toString().slice(2);
}
private function getYearLastDigit(val:int):String {
return val.toString().slice(3);
}
// new version
private function numStepperChange2(e:*):void {
var initial:int = numStepper.value ;
var date:Date = new Date();
var timeStr:String = date.getTime().toString();
//timeStr.slice(7) +
//var dateStr:String = initial + "0"+ padd() + padd(date.getMonth()) + "4";// timeStr.slice(timeStr.length - 3,1) + "10"+ initial+ padd(date.getDate()) + padd(date.getMonth()) + getYear(date.getFullYear()) + timeStr.slice(timeStr.length - 2);
//,4,date.getDate(), date.getMonth()+1, date.getFullYear() - 2000
var encoded:String = encodeNewId(initial);
labeler.text = encoded;//AlphaID.encode(numStepper.value);
labeler2.text = ""+encoded + " :: "+hashIds.decode(encoded) ;
txtBox.text = timeStr;
}
// old version
private function numStepperChange(e:*):void {
var initial:int = numStepper.value ;
var date:Date = new Date();
var timeStr:String = date.getTime().toString();
//timeStr.slice(7) +
var dateStr:String = initial + "0"+ padd(date.getDate()) + padd(date.getMonth()) + "4";// timeStr.slice(timeStr.length - 3,1) + "10"+ initial+ padd(date.getDate()) + padd(date.getMonth()) + getYear(date.getFullYear()) + timeStr.slice(timeStr.length - 2);
labeler.text = dateStr;//AlphaID.encode(numStepper.value);
if (int(labeler.text) != Number(labeler.text)) {
labeler.text = "SORRY";
return;
}
var encoded:String = AlphaID.encode( int(labeler.text) );
labeler2.text = ""+encoded + " :: "+AlphaID.decode(encoded); //
txtBox.text = timeStr;
}
}
}
class HashIds {
public function HashIds(salt : String ,minHashLength : int = 0,alphabet : String = null) : void { if( true ) {
var uniqueAlphabet : String, i : int, j : int, len : int, sepsLength : int, diff : int, guardCount : int;
this.version = "1.0.2";
this.minAlphabetLength = 16;
this.sepDiv = 3.5;
this.guardDiv = 12;
this.errorAlphabetLength = "error: alphabet must contain at least X unique characters";
this.errorAlphabetSpace = "error: alphabet cannot contain spaces";
this.alphabet = ((alphabet != null)?alphabet:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
this.seps = "cfhistuCFHISTU";
this.minHashLength = ((minHashLength > 0)?minHashLength:0);
this.salt = salt;
uniqueAlphabet = "";
i = 0;
len = this.alphabet.length;
while(i != len) {
if(uniqueAlphabet.indexOf(this.alphabet.charAt(i)) == -1) uniqueAlphabet += this.alphabet.charAt(i);
i++;
};
this.alphabet = uniqueAlphabet;
if(this.alphabet.length < this.minAlphabetLength) throw StringTools.replace(this.errorAlphabetLength,"X",String(this.minAlphabetLength));
if(this.alphabet.indexOf(" ") != -1) throw this.errorAlphabetSpace;
i = 0;
len = this.seps.length;
while(i != len) {
j = this.alphabet.indexOf(this.seps.charAt(i));
if(j == -1) this.seps = this.seps.substr(0,i) + " " + this.seps.substr(i + 1);
else this.alphabet = this.alphabet.substr(0,j) + " " + this.alphabet.substr(j + 1);
i++;
};
this.alphabet = new EReg(" ","g").replace(this.alphabet,"");
this.seps = new EReg(" ","g").replace(this.seps,"");
this.seps = this.consistentShuffle(this.seps,this.salt);
if(!(this.seps.length != 0) || this.alphabet.length / this.seps.length > this.sepDiv) {
sepsLength = Math.ceil(this.alphabet.length / this.sepDiv);
if(sepsLength == 1) sepsLength++;
if(sepsLength > this.seps.length) {
diff = sepsLength - this.seps.length;
this.seps += this.alphabet.substr(0,diff);
this.alphabet = this.alphabet.substr(diff);
}
else this.seps = this.seps.substr(0,sepsLength);
};
this.alphabet = this.consistentShuffle(this.alphabet,this.salt);
guardCount = Math.ceil(this.alphabet.length / this.guardDiv);
if(this.alphabet.length < 3) {
this.guards = this.seps.substr(0,guardCount);
this.seps = this.seps.substr(guardCount);
}
else {
this.guards = this.alphabet.substr(0,guardCount);
this.alphabet = this.alphabet.substr(guardCount);
}
}}
public function unhash(input : String,alphabet : String) : Number {
var number : Number = 0, pos : int, i : int;
i = 0;
{
var _g1 : int = 0, _g : int = input.length;
while(_g1 < _g) {
var i1 : int = _g1++;
pos = alphabet.indexOf(input.charAt(i1));
number += pos * Math.pow(alphabet.length,input.length - i1 - 1);
}
};
return number;
}
public function hash(input : uint,alphabet : *) : String {
var hash : String = "", alphabetLength : int = alphabet.length;
do {
hash = alphabet.charAt(input % alphabetLength) + hash;
input =int(input / alphabetLength);
} while(input != 0);
return hash;
}
public function consistentShuffle(alphabet : String,salt : String) : String {
var integer : *, j : int, temp : String, i : *, v : int, p : int;
if(salt.length == 0) return alphabet;
var i1 : int = alphabet.length - 1;
v = 0;
p = 0;
while(i1 > 0) {
v %= salt.length;
p += integer = salt.charAt(v).charCodeAt(0);
j = (integer + v + p) % i1;
temp = alphabet.charAt(j);
alphabet = alphabet.substr(0,j) + alphabet.charAt(i1) + alphabet.substr(j + 1);
alphabet = alphabet.substr(0,i1) + temp + alphabet.substr(i1 + 1);
i1--;
v++;
};
return alphabet;
}
public function _decode(hash : String,alphabet : String) : Array {
var ret : Array = [], i : int = 0, lottery : String, len : int, subHash : String, buffer : String, r : EReg = new EReg("[" + this.guards + "]","g"), hashBreakdown : String = r.replace(hash," ");
var hashArray : Array = hashBreakdown.split(" ");
if(hashArray.length == 3 || hashArray.length == 2) i = 1;
hashBreakdown = hashArray[i];
if(hashBreakdown.charAt(0) != null) {
lottery = hashBreakdown.charAt(0);
hashBreakdown = hashBreakdown.substr(1);
r = new EReg("[" + this.seps + "]","g");
hashBreakdown = r.replace(hashBreakdown," ");
hashArray = hashBreakdown.split(" ");
i = 0;
len = hashArray.length;
while(i != len) {
subHash = hashArray[i];
buffer = lottery + this.salt + alphabet;
alphabet = this.consistentShuffle(alphabet,buffer.substr(0,alphabet.length));
ret.push(this.unhash(subHash,alphabet));
i++;
};
if(this._encode(ret) != hash) ret = [];
};
return ret;
}
public function _encode(numbers : Array) : String {
var ret : String, lottery : String, i : *, len : *, number : uint, buffer : String, last : String, sepsIndex : uint, guardIndex : int, guard : String, halfLength : int, excess : int, alphabet : String = this.alphabet, numbersSize : int = numbers.length, numbersHashInt : Number = 0;
var i1 : int = 0;
var len1 : int = numbers.length;
while(i1 != len1) {
numbersHashInt += numbers[i1] % (i1 + 100);
i1++;
};
lottery = ret = alphabet.charAt(int(numbersHashInt % alphabet.length));
i1 = 0;
len1 = numbers.length;
while(i1 != len1) {
number = numbers[i1];
buffer = lottery + this.salt + alphabet;
alphabet = this.consistentShuffle(alphabet,buffer.substr(0,alphabet.length));
last = this.hash(number,alphabet);
ret += last;
if(i1 + 1 < numbersSize) {
number %= last.charCodeAt(0) + i1;
sepsIndex = number % this.seps.length;
ret += this.seps.charAt(sepsIndex);
};
i1++;
};
if(ret.length < this.minHashLength) {
guardIndex =int((numbersHashInt + ret.charCodeAt(0)) % this.guards.length);
guard = this.guards.charAt(guardIndex);
ret = guard + ret;
if(ret.length < this.minHashLength) {
guardIndex =int((numbersHashInt + ret.charCodeAt(2)) % this.guards.length);
guard = this.guards.charAt(guardIndex);
ret += guard;
}
};
halfLength =int(alphabet.length / 2);
while(ret.length < this.minHashLength) {
alphabet = this.consistentShuffle(alphabet,alphabet);
ret = alphabet.substr(halfLength) + ret + alphabet.substr(0,halfLength);
excess = ret.length - this.minHashLength;
if(excess > 0) ret = ret.substr(int(excess / 2),this.minHashLength);
};
return ret;
}
public function decode(hash : String) : Array {
if(!(hash.length != 0)) return [];
return this._decode(hash,this.alphabet);
}
public function encode(numbers : Array) : String {
return this._encode(numbers);
}
public var guards : String;
public var seps : String;
public var minHashLength : int;
public var errorAlphabetSpace : String;
public var errorAlphabetLength : String;
public var guardDiv : Number;
public var sepDiv : Number;
public var minAlphabetLength : Number;
public var version : String;
public var salt : String;
public var alphabet : String;
}
class AlphaID {
static public var index : String = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static public function encode(_number : int) : String {
var strBuf : StringBuf = new StringBuf();
var i : int = 0;
var end : int = Math.floor(Math.log(_number) / Math.log(AlphaID.index.length));
while(i <= end) strBuf.add(AlphaID.index.charAt(Math.floor(_number / AlphaID.bcpow(AlphaID.index.length,i++)) % AlphaID.index.length) );
return strBuf.toString();
}
static public function decode(_string : String) : int {
var str : String = AlphaID.reverseString(_string);
var ret : int = 0;
var i : int = 0;
var end : int = str.length - 1;
while(i <= end) {
ret += int(AlphaID.index.indexOf(str.charAt(i)) * AlphaID.bcpow(AlphaID.index.length,end - i));
++i;
};
return ret;
}
static protected function bcpow(_a : Number,_b : Number) : Number {
return Math.floor(Math.pow(_a,_b));
}
static protected function reverseString(inStr : String) : String {
var ary : Array = inStr.split("");
ary.reverse();
return ary.join("");
}
}
class StringTools {
static public function urlEncode(s : String) : String {
return encodeURIComponent(s);
}
static public function urlDecode(s : String) : String {
return decodeURIComponent(s.split("+").join(" "));
}
static public function htmlEscape(s : String,quotes : * = null) : String {
s = s.split("&").join("&").split("<").join("<").split(">").join(">");
return ((quotes)?s.split("\"").join(""").split("'").join("'"):s);
}
static public function htmlUnescape(s : String) : String {
return s.split(">").join(">").split("<").join("<").split(""").join("\"").split("'").join("'").split("&").join("&");
}
static public function startsWith(s : String,start : String) : Boolean {
return s.length >= start.length && s.substr(0,start.length) == start;
}
static public function endsWith(s : String,end : String) : Boolean {
var elen : int = end.length;
var slen : int = s.length;
return slen >= elen && s.substr(slen - elen,elen) == end;
}
static public function isSpace(s : String,pos : int) : Boolean {
var c : * = s.charCodeAt(pos);
return c > 8 && c < 14 || c == 32;
}
static public function ltrim(s : String) : String {
var l : int = s.length;
var r : int = 0;
while(r < l && StringTools.isSpace(s,r)) r++;
if(r > 0) return s.substr(r,l - r);
else return s;
return null;
}
static public function rtrim(s : String) : String {
var l : int = s.length;
var r : int = 0;
while(r < l && StringTools.isSpace(s,l - r - 1)) r++;
if(r > 0) return s.substr(0,l - r);
else return s;
return null;
}
static public function trim(s : String) : String {
return StringTools.ltrim(StringTools.rtrim(s));
}
static public function lpad(s : String,c : String,l : int) : String {
if(c.length <= 0) return s;
while(s.length < l) s = c + s;
return s;
}
static public function rpad(s : String,c : String,l : int) : String {
if(c.length <= 0) return s;
while(s.length < l) s = s + c;
return s;
}
static public function replace(s : String,sub : String,by : String) : String {
return s.split(sub).join(by);
}
static public function hex(n : int,digits : * = null) : String {
var n1 : uint = n;
var s : String = n1.toString(16);
s = s.toUpperCase();
if(digits != null) while(s.length < digits) s = "0" + s;
return s;
}
static public function fastCodeAt(s : String,index : int) : int {
return s.charCodeAt(index);
}
static public function isEof(c : int) : Boolean {
return c == 0;
}
}
class EReg {
public function EReg(r : String = null,opt : String = null) : void {
this.r = new RegExp(r,opt);
}
public function map(s : String,f : Function) : String {
var offset : int = 0;
var buf : StringBuf = new StringBuf();
var first : Boolean = true;
do {
if(offset >= s.length) break;
else if(!this.matchSub(s,offset)) {
buf.add(s.substr(offset));
break;
};
var p : * = this.matchedPos();
buf.add(s.substr(offset,p.pos - offset));
buf.add(f(this));
if(p.len == 0) {
buf.add(s.substr(p.pos,1));
offset = p.pos + 1;
}
else offset = p.pos + p.len;
first = false;
} while(this.r.global);
if(!this.r.global && offset > 0 && offset < s.length) buf.add(s.substr(offset));
return buf.toString();
}
public function replace(s : String,by : String) : String {
return s.replace(this.r,by);
}
public function split(s : String) : Array {
var d : String = "#__delim__#";
var s1 : String = s.replace(this.r,d);
return s1.split(d);
}
public function matchSub(s : String,pos : int,len : int = -1) : Boolean {
return ((this.r.global)?(function($this:EReg) : Boolean {
var $r : Boolean;
$this.r.lastIndex = pos;
$this.result = $this.r.exec(((len < 0)?s:s.substr(0,pos + len)));
var b : Boolean = $this.result != null;
if(b) $this.result.input = s;
$r = b;
return $r;
}(this)):(function($this:EReg) : Boolean {
var $r2 : Boolean;
var b1 : Boolean = $this.match(((len < 0)?s.substr(pos):s.substr(pos,len)));
if(b1) {
$this.result.input = s;
$this.result.index += pos;
}
$r2 = b1;
return $r2;
}(this)));
}
public function matchedPos() : * {
if(this.result == null) throw "No string matched";
return { pos : this.result.index, len : this.result[0].length}
}
public function matchedRight() : String {
if(this.result == null) throw "No string matched";
var rl : int = this.result.index + this.result[0].length;
var s : String = this.result.input;
return s.substr(rl,s.length - rl);
}
public function matchedLeft() : String {
if(this.result == null) throw "No string matched";
var s : String = this.result.input;
return s.substr(0,this.result.index);
}
public function matched(n : int) : String {
return ((this.result != null && n >= 0 && n < this.result.length)?this.result[n]:(function($this:EReg) : String {
var $r : String;
throw "EReg::matched";
return $r;
}(this)));
}
public function match(s : String) : Boolean {
if(this.r.global) this.r.lastIndex = 0;
this.result = this.r.exec(s);
return this.result != null;
}
protected var result : *;
public var r : RegExp;
}