<commit_before>export default [
    '(business|client|community|culture|customer|data|goal|intelligence|market' +
        '|process|quality|results|role|sales|subject|service|user)' +
        '.(centric(ity)?|facing|oriented|driven|focused|assessment|service|process)',
    '10x',
    '24/7',
    'ai',
    'agile',
    'ambassador',
    'artificial intelligence',
    'at (your|their) fingertips?',
    'autonomous',
    'a[-/]b testing',
    'acquisition',
    'action items?',
    'act in time',
    'advantages?',
    'agents?',
    'aggregat(e|ion)',
    'accelerate',
    'all.in.one',
    'all.new',
    'amazing',
    'analytics?',
    'application service providers?',
    'as a service',
    'assets?',
    'astonishing',
    'authoritative',
    'automated',
    'augmented',
    'extended reality',
    'award.winning',
    'b2(b|c)',
    'back to the drawing board',
    'ball.?park',
    'band.aid',
    'bandwidth',
    '(benefit|gap) analysis',
    'bespoke',
    'best.in.class',
    'best.of.breed',
    'best.practice',
    'big.data',
    'big picture',
    'big thinkers?',
    'block.?chain',
    'blazing(ly)? fast',
    'boil the ocean',
    'bottom.line',
    'bottom.up',
    'boost(s|ing)?',
    'brain.?storm(ing)?',
    'brain.?dump',
    'brand(s?|ing|ed)',
    'bright',
    'building.trust',
    'bulletproof',
    'burn.rates?',
    'business( cases| plans)',
    'buzz',
    'call to action',
    'capacity',
    'capabilit(y|ies)',
    'capitali(s|z)e',
    'centers? of excellence',
    'challenges?',
    'change agents?',
    'circle the wagons',
    'client-centered',
    'client-centric',
    'client-focused',
    'cloud',
    'cloud native',
    'cloudify',
    'collaborat(e|ion|ive)s?',
    'comfort( zone)?',
    'committee',
    'communicat(e|ion)s?',
    'company-employee.fit',
    'compelling',
    'competitive( advantage)?',
    'connected systems?',
    'complex(ity)?',
    'comprehensive',
    'connect the dots',
    'container orchestration',
    'containerizat(e|ion|ing)',
    'content management',
    'contextual(ly)?',
    'contingency plans?',
    'control groups?',
    'control plane',
    'convergence',
    'convergent',
    'conversions?',
    'core business',
    'core competenc(y|ies)',
    'core.to.edge',
    'cosmic',
    'cost-effective',
    'cost/benefit',
    'cost control',
    'craftsmanship',
    'critical path',
    'crypto.currency',
    'crypto(?!graphy).\\w+',
    'crm',
    'cross.sell',
    'crowd.?(fund(s?|ed|ing)|sourc(ed|e|ing))',
    'customer obsession',
    'cutting.edge',
    'cyber',
    'dashboards?',
    'dashboarding',
    'data mining',
    'decentrali(s|z)ed',
    'de-?dupe',
    'deep dive',
    'deep learning',
    'delight',
    'deliverables?',
    'demographic',
    'demystify',
    'demystifying',
    'deployless',
    'devops',
    'digital transformation',
    'discovery',
    'distributed ledgers?',
    'disrupt(ive|tor|ion)?',
    'dollar.productive',
    'downsi(s|z)e',
    'drill down',
    'drink the kool-aid',
    'drop.?in',
    'drop the ball',
    'due dilligence',
    'dynamic(s|ally)?',
    'e-?(business|commerce|tailers)',
    'early.stage',
    'eas(y|ily)',
    'ecosystems?',
    'efficien(t|cy)',
    'effortless(ly)?',
    'elastic',
    'elaboration',
    'elephant in the room',
    'elevator pitch(ing)?',
    'enabl(e|ing)',
    'emerging markets?',
    'empower(ing|ment|s)?',
    'enablement',
    'end of the day',
    'end.to.end',
    'engulf',
    'engag(e|ing|ment)',
    'enhanced?',
    'enterprise',
    'erp',
    'estimate',
    'eta',
    'etched in stone',
    'evolution',
    'exceed expectations',
    'exclusive(ly)?',
    'exhaustive',
    'expedite',
    'experiences',
    'experts?',
    'expertise',
    'exposure',
    'extraordinary',
    'facilitat(e|or)',
    'fast track',
    'fault.tolerant',
    'first.to.market',
    'flexibility',
    'flux',
    'foot view',
    'forward-thinking',
    'four pillars',
    'frictionless',
    'front lines',
    'frustration[- ]free',
    'functional',
    'futurist',
    'full benefit',
    'future.proof',
    'game changer',
    'game plan',
    'behavioral',
    'global(ly)?',
    'go public',
    'go.to.market',
    'goals?',
    'god-speed',
    'going forward',
    'granular',
    'ground.?breaking',
    'growth',
    'grow',
    'guidance',
    'guru',
    'hackathon',
    'hacker( mindset)?',
    'happiness manage(ment|rs?)',
    'hardball',
    'heavy.lifting',
    'herding cats',
    'hidden.gem',
    'hidden.meaning',
    'high.level',
    '(high|mass).impact',
    'highly.scalable',
    'hive ?mind',
    'hybrid environments?',
    'hyper.personalization',
    'hyperconverged',
    'holistic',
    'impactful',
    'impeccable',
    'in( |-)a( |-)nutshell',
    'incent',
    'incentivi(s|z)e',
    'increase the odds',
    'incredibl(e|y)',
    '(inflat|redeem)able value',
    'influencers?',
    'influx',
    'innovat(e|ed|ion|ive|ing|or)s?',
    'inspir(e|ing|ation)',
    'insights?',
    'integrat(e|ed|ion)s?',
    'internet[- ]of[- ]things',
    'intellectual property',
    'intuitive',
    'iot',
    'key results?',
    'kickstart(er|ed)?s?',
    'killjoy',
    'knowledge.(base|transfer|sharing)',
    'kpis?',
    'landing pages?',
    'lead the field',
    'leading',
    'leaders?',
    'leadership',
    'learnings',
    'legacy',
    'lessons learned',
    'level (the )? playing field',
    'level set',
    'leverag(e|ing)',
    'lifecycle',
    'low.hanging fruit',
    'look.(&|and).feel',
    'm2m',
    'machine learning',
    'made simple',
    'magical',
    'market (chang(er|ing)|leader|window|simplified|fit)',
    'market.ready',
    'marketing collateral',
    'maximi(s|z)e',
    'meaningful( client | )interactions?',
    'measurements?',
    'methodolog(y|ies)',
    'metrics',
    'middleware',
    'milestone',
    'military.grade encryption',
    'mind ?share',
    'mind ?shower',
    'mind-boggling',
    'mindset',
    '(mission|time).critical',
    'ml',
    'moneti(s|z)e',
    'mov(e|ing) (fast|forward)',
    'multitask(ing?)',
    'multifaceted',
    'multi-?tenant(ed)?',
    'mvp',
    'negotiated',
    'networking',
    'new.economy',
    'new.breed',
    '(new|next|second).(level|gen|generation)',
    'niches?',
    'ninja',
    'no-brainer',
    'non-traditional management',
    'objectives',
    'occupy the field',
    'off.site',
    'off.the.(radar|shelf)',
    'on board',
    'on.premises?',
    'on the (back end|radar screen|same page|house)',
    'one to one',
    'open the kimono',
    'opportunit(y|ies)',
    'outperform',
    'optimal',
    'orthogonal',
    'outstanding',
    'out(side)?.of.the.(box|loop)',
    'outsourc(e|ed|ing)',
    '(total cost of )?ownership',
    'paradigms?( shift)?',
    'partner(ships?)?',
    'patents?',
    'performance indicators',
    'personaliz(e|ed|ation)',
    'perspective',
    'phases?',
    'phased approach',
    'pipeline',
    'pioneers',
    'pivot',
    'planning horizon',
    'platforms?',
    'plug.?in',
    'potentials?',
    'powerful',
    'prioriti(s|z)ed?',
    'proactive',
    'problem space',
    'processes',
    'profit(ability)?',
    'promotion',
    'promotional collateral',
    'prominent',
    'proprietary',
    'proof.of.concept',
    'purpose.built',
    'push the envelope',
    'push.back',
    'production.ready',
    'productivity',
    'pushing on open doors',
    'quick wins?',
    'rais(e|ing) the bar',
    'ramp.up',
    'ravishing',
    'relationship management',
    'responsive',
    'engage(ments?)?',
    'reach out',
    'reactivation',
    'real.time',
    'real.world',
    'reconfigure',
    'redefin(e|ed|ing)',
    'red flags?',
    'reengineering',
    'reinvent(ing)? the(.square)? wheel',
    'reinvigorate',
    'relevance',
    'repurpose',
    'resilien(ce|cy|t)',
    'resource allocation',
    'restructuring',
    'retention',
    'return on investment',
    'results',
    'reus(e|ability)',
    'revenue',
    'reverse.engineer',
    'revisit',
    'revolution',
    'rich',
    'road ?map',
    'robust',
    'rock.?star',
    'roi',
    'run the numbers',
    '(s|p)aas',
    'sacrific(e|es|ing)',
    'scal(e|es|ing|ability)',
    'high availability',
    'scenarios?',
    'scope',
    'scrum( master)?',
    'seamless',
    'secret sauce',
    'search engine optimization',
    'segments?',
    'self-managed team',
    'seo',
    '(serial )?entrepreneurs?',
    'serverless',
    'service mesh',
    'shareholder value',
    'significant(ly)?',
    'single-source responsibility',
    'skill ?sets?',
    'smart(er)?',
    'smoke (&|and) mirrors',
    'social(.media|.gaming|.networks?)',
    'solidality',
    'solutions?',
    'sophisticated',
    'soup to nuts',
    'sow',
    'spatial.computing',
    'stakeholders?',
    'start.up?',
    'statement of work',
    'state.of.the.art',
    'step.changes?',
    'sticky-?ness',
    'strateg(y|ic|ize|ise)',
    'streamlin(ed|e|ing)',
    'story points?',
    'success(ful)?',
    'super(critical|star|nova)',
    'sustainab(le|ility)',
    'synerg(y|ies|ized|i)',
    'systems?',
    'tailwinds?',
    'talented',
    'take offline',
    'talking points',
    'target (audience|group)',
    'targeted',
    'tasked',
    'tco',
    'team.building',
    'team.player',
    'teamwork',
    'technolog(y|ies)',
    'that being said',
    'throughput',
    'time.to.awesome',
    'time.to.market',
    'timelines?',
    'top.down',
    'top.of.the.game',
    'total quality',
    'touch.base',
    'touchpoints?',
    'traction',
    'transfor(m|ming)',
    'trends?',
    'true',
    'truths?',
    'turnkey',
    'ultimate',
    'up.to.speed',
    'up-?sell',
    'upside',
    'user.friendly',
    'user funnels?',
    'user.experience',
    'utili(s|z)(e|ation)',
    'uncover',
    'unicorn',
    'unique approach',
    'unlimited.holidays',
    'values?',
    'valueable',
    'value.add(ed)?',
    'venture',
    'venturing',
    'vertical market',
    'viral',
    'virtual(ization|isation)?',
    'visibility',
    'visio(n|nary)',
    'walk the talk',
    'wearable',
    'web.enabled',
    'win-win',
    'wisdom of crowds',
    'with due respect',
    'with ease',
    'wizards?',
    'workflows?',
    'workloads?',
    'workplaceless',
    'workspace',
    'world.?class',
    'world a better place',
    'wow.factor',
    'you\'ve never seen (a|an) \\w+',
    'zeitgeist',
];
<commit_msg>Added reimagine variants (#131)<commit_after>export default [
    '(business|client|community|culture|customer|data|goal|intelligence|market' +
        '|process|quality|results|role|sales|subject|service|user)' +
        '.(centric(ity)?|facing|oriented|driven|focused|assessment|service|process)',
    '10x',
    '24/7',
    'ai',
    'agile',
    'ambassador',
    'artificial intelligence',
    'at (your|their) fingertips?',
    'autonomous',
    'a[-/]b testing',
    'acquisition',
    'action items?',
    'act in time',
    'advantages?',
    'agents?',
    'aggregat(e|ion)',
    'accelerate',
    'all.in.one',
    'all.new',
    'amazing',
    'analytics?',
    'application service providers?',
    'as a service',
    'assets?',
    'astonishing',
    'authoritative',
    'automated',
    'augmented',
    'extended reality',
    'award.winning',
    'b2(b|c)',
    'back to the drawing board',
    'ball.?park',
    'band.aid',
    'bandwidth',
    '(benefit|gap) analysis',
    'bespoke',
    'best.in.class',
    'best.of.breed',
    'best.practice',
    'big.data',
    'big picture',
    'big thinkers?',
    'block.?chain',
    'blazing(ly)? fast',
    'boil the ocean',
    'bottom.line',
    'bottom.up',
    'boost(s|ing)?',
    'brain.?storm(ing)?',
    'brain.?dump',
    'brand(s?|ing|ed)',
    'bright',
    'building.trust',
    'bulletproof',
    'burn.rates?',
    'business( cases| plans)',
    'buzz',
    'call to action',
    'capacity',
    'capabilit(y|ies)',
    'capitali(s|z)e',
    'centers? of excellence',
    'challenges?',
    'change agents?',
    'circle the wagons',
    'client-centered',
    'client-centric',
    'client-focused',
    'cloud',
    'cloud native',
    'cloudify',
    'collaborat(e|ion|ive)s?',
    'comfort( zone)?',
    'committee',
    'communicat(e|ion)s?',
    'company-employee.fit',
    'compelling',
    'competitive( advantage)?',
    'connected systems?',
    'complex(ity)?',
    'comprehensive',
    'connect the dots',
    'container orchestration',
    'containerizat(e|ion|ing)',
    'content management',
    'contextual(ly)?',
    'contingency plans?',
    'control groups?',
    'control plane',
    'convergence',
    'convergent',
    'conversions?',
    'core business',
    'core competenc(y|ies)',
    'core.to.edge',
    'cosmic',
    'cost-effective',
    'cost/benefit',
    'cost control',
    'craftsmanship',
    'critical path',
    'crypto.currency',
    'crypto(?!graphy).\\w+',
    'crm',
    'cross.sell',
    'crowd.?(fund(s?|ed|ing)|sourc(ed|e|ing))',
    'customer obsession',
    'cutting.edge',
    'cyber',
    'dashboards?',
    'dashboarding',
    'data mining',
    'decentrali(s|z)ed',
    'de-?dupe',
    'deep dive',
    'deep learning',
    'delight',
    'deliverables?',
    'demographic',
    'demystify',
    'demystifying',
    'deployless',
    'devops',
    'digital transformation',
    'discovery',
    'distributed ledgers?',
    'disrupt(ive|tor|ion)?',
    'dollar.productive',
    'downsi(s|z)e',
    'drill down',
    'drink the kool-aid',
    'drop.?in',
    'drop the ball',
    'due dilligence',
    'dynamic(s|ally)?',
    'e-?(business|commerce|tailers)',
    'early.stage',
    'eas(y|ily)',
    'ecosystems?',
    'efficien(t|cy)',
    'effortless(ly)?',
    'elastic',
    'elaboration',
    'elephant in the room',
    'elevator pitch(ing)?',
    'enabl(e|ing)',
    'emerging markets?',
    'empower(ing|ment|s)?',
    'enablement',
    'end of the day',
    'end.to.end',
    'engulf',
    'engag(e|ing|ment)',
    'enhanced?',
    'enterprise',
    'erp',
    'estimate',
    'eta',
    'etched in stone',
    'evolution',
    'exceed expectations',
    'exclusive(ly)?',
    'exhaustive',
    'expedite',
    'experiences',
    'experts?',
    'expertise',
    'exposure',
    'extraordinary',
    'facilitat(e|or)',
    'fast track',
    'fault.tolerant',
    'first.to.market',
    'flexibility',
    'flux',
    'foot view',
    'forward-thinking',
    'four pillars',
    'frictionless',
    'front lines',
    'frustration[- ]free',
    'functional',
    'futurist',
    'full benefit',
    'future.proof',
    'game changer',
    'game plan',
    'behavioral',
    'global(ly)?',
    'go public',
    'go.to.market',
    'goals?',
    'god-speed',
    'going forward',
    'granular',
    'ground.?breaking',
    'growth',
    'grow',
    'guidance',
    'guru',
    'hackathon',
    'hacker( mindset)?',
    'happiness manage(ment|rs?)',
    'hardball',
    'heavy.lifting',
    'herding cats',
    'hidden.gem',
    'hidden.meaning',
    'high.level',
    '(high|mass).impact',
    'highly.scalable',
    'hive ?mind',
    'hybrid environments?',
    'hyper.personalization',
    'hyperconverged',
    'holistic',
    'impactful',
    'impeccable',
    'in( |-)a( |-)nutshell',
    'incent',
    'incentivi(s|z)e',
    'increase the odds',
    'incredibl(e|y)',
    '(inflat|redeem)able value',
    'influencers?',
    'influx',
    'innovat(e|ed|ion|ive|ing|or)s?',
    'inspir(e|ing|ation)',
    'insights?',
    'integrat(e|ed|ion)s?',
    'internet[- ]of[- ]things',
    'intellectual property',
    'intuitive',
    'iot',
    'key results?',
    'kickstart(er|ed)?s?',
    'killjoy',
    'knowledge.(base|transfer|sharing)',
    'kpis?',
    'landing pages?',
    'lead the field',
    'leading',
    'leaders?',
    'leadership',
    'learnings',
    'legacy',
    'lessons learned',
    'level (the )? playing field',
    'level set',
    'leverag(e|ing)',
    'lifecycle',
    'low.hanging fruit',
    'look.(&|and).feel',
    'm2m',
    'machine learning',
    'made simple',
    'magical',
    'market (chang(er|ing)|leader|window|simplified|fit)',
    'market.ready',
    'marketing collateral',
    'maximi(s|z)e',
    'meaningful( client | )interactions?',
    'measurements?',
    'methodolog(y|ies)',
    'metrics',
    'middleware',
    'milestone',
    'military.grade encryption',
    'mind ?share',
    'mind ?shower',
    'mind-boggling',
    'mindset',
    '(mission|time).critical',
    'ml',
    'moneti(s|z)e',
    'mov(e|ing) (fast|forward)',
    'multitask(ing?)',
    'multifaceted',
    'multi-?tenant(ed)?',
    'mvp',
    'negotiated',
    'networking',
    'new.economy',
    'new.breed',
    '(new|next|second).(level|gen|generation)',
    'niches?',
    'ninja',
    'no-brainer',
    'non-traditional management',
    'objectives',
    'occupy the field',
    'off.site',
    'off.the.(radar|shelf)',
    'on board',
    'on.premises?',
    'on the (back end|radar screen|same page|house)',
    'one to one',
    'open the kimono',
    'opportunit(y|ies)',
    'outperform',
    'optimal',
    'orthogonal',
    'outstanding',
    'out(side)?.of.the.(box|loop)',
    'outsourc(e|ed|ing)',
    '(total cost of )?ownership',
    'paradigms?( shift)?',
    'partner(ships?)?',
    'patents?',
    'performance indicators',
    'personaliz(e|ed|ation)',
    'perspective',
    'phases?',
    'phased approach',
    'pipeline',
    'pioneers',
    'pivot',
    'planning horizon',
    'platforms?',
    'plug.?in',
    'potentials?',
    'powerful',
    'prioriti(s|z)ed?',
    'proactive',
    'problem space',
    'processes',
    'profit(ability)?',
    'promotion',
    'promotional collateral',
    'prominent',
    'proprietary',
    'proof.of.concept',
    'purpose.built',
    'push the envelope',
    'push.back',
    'production.ready',
    'productivity',
    'pushing on open doors',
    'quick wins?',
    'rais(e|ing) the bar',
    'ramp.up',
    'ravishing',
    'relationship management',
    'responsive',
    'engage(ments?)?',
    'reach out',
    'reactivation',
    'real.time',
    'real.world',
    'reconfigure',
    'redefin(e|ed|ing)',
    'red flags?',
    'reengineering',
    'reimagin(e|ed|ing)',
    'reinvent(ing)? the(.square)? wheel',
    'reinvigorate',
    'relevance',
    'repurpose',
    'resilien(ce|cy|t)',
    'resource allocation',
    'restructuring',
    'retention',
    'return on investment',
    'results',
    'reus(e|ability)',
    'revenue',
    'reverse.engineer',
    'revisit',
    'revolution',
    'rich',
    'road ?map',
    'robust',
    'rock.?star',
    'roi',
    'run the numbers',
    '(s|p)aas',
    'sacrific(e|es|ing)',
    'scal(e|es|ing|ability)',
    'high availability',
    'scenarios?',
    'scope',
    'scrum( master)?',
    'seamless',
    'secret sauce',
    'search engine optimization',
    'segments?',
    'self-managed team',
    'seo',
    '(serial )?entrepreneurs?',
    'serverless',
    'service mesh',
    'shareholder value',
    'significant(ly)?',
    'single-source responsibility',
    'skill ?sets?',
    'smart(er)?',
    'smoke (&|and) mirrors',
    'social(.media|.gaming|.networks?)',
    'solidality',
    'solutions?',
    'sophisticated',
    'soup to nuts',
    'sow',
    'spatial.computing',
    'stakeholders?',
    'start.up?',
    'statement of work',
    'state.of.the.art',
    'step.changes?',
    'sticky-?ness',
    'strateg(y|ic|ize|ise)',
    'streamlin(ed|e|ing)',
    'story points?',
    'success(ful)?',
    'super(critical|star|nova)',
    'sustainab(le|ility)',
    'synerg(y|ies|ized|i)',
    'systems?',
    'tailwinds?',
    'talented',
    'take offline',
    'talking points',
    'target (audience|group)',
    'targeted',
    'tasked',
    'tco',
    'team.building',
    'team.player',
    'teamwork',
    'technolog(y|ies)',
    'that being said',
    'throughput',
    'time.to.awesome',
    'time.to.market',
    'timelines?',
    'top.down',
    'top.of.the.game',
    'total quality',
    'touch.base',
    'touchpoints?',
    'traction',
    'transfor(m|ming)',
    'trends?',
    'true',
    'truths?',
    'turnkey',
    'ultimate',
    'up.to.speed',
    'up-?sell',
    'upside',
    'user.friendly',
    'user funnels?',
    'user.experience',
    'utili(s|z)(e|ation)',
    'uncover',
    'unicorn',
    'unique approach',
    'unlimited.holidays',
    'values?',
    'valueable',
    'value.add(ed)?',
    'venture',
    'venturing',
    'vertical market',
    'viral',
    'virtual(ization|isation)?',
    'visibility',
    'visio(n|nary)',
    'walk the talk',
    'wearable',
    'web.enabled',
    'win-win',
    'wisdom of crowds',
    'with due respect',
    'with ease',
    'wizards?',
    'workflows?',
    'workloads?',
    'workplaceless',
    'workspace',
    'world.?class',
    'world a better place',
    'wow.factor',
    'you\'ve never seen (a|an) \\w+',
    'zeitgeist',
];
<|endoftext|>


<commit_before>export default [
    '(business|client|community|culture|customer|data|goal|intelligence|market' +
        '|process|quality|results|role|sales|subject|service|user)' +
        '.(centric(ity)?|facing|oriented|driven|focused|assessment|service|process)',
    '24/7',
    'ai',
    'agile',
    'ambassador',
    'artificial intelligence',
    'at (your|their) fingertips',
    'autonomous',
    'a[-/]b testing',
    'acquisition',
    'action items?',
    'act in time',
    'advantages?',
    'agents?',
    'aggregat(e|ion)',
    'accelerate',
    'all.in.one',
    'all.new',
    'amazing',
    'analytics?',
    'application service providers?',
    'as a service',
    'assets?',
    'astonishing',
    'authoritative',
    'automated',
    'augmented',
    'extended reality',
    'award.winning',
    'b2(b|c)',
    'back to the drawing board',
    'ball.?park',
    'band.aid',
    'bandwidth',
    '(benefit|gap) analysis',
    'bespoke',
    'best.in.class',
    'best.of.breed',
    'best.practice',
    'big.data',
    'big picture',
    'big thinkers?',
    'block.?chain',
    'blazing(ly)? fast',
    'bottom.line',
    'bottom.up',
    'boost(s|ing)?',
    'brain.?storm(ing)?',
    'brain.?dump',
    'brand(s?|ing|ed)',
    'bright',
    'building.trust',
    'bulletproof',
    'burn.rates?',
    'business( cases| plans)',
    'buzz',
    'call to action',
    'capacity',
    'capabilit(y|ies)',
    'capitali(s|z)e',
    'centers? of excellence',
    'challenges?',
    'change agents?',
    'circle the wagons',
    'client-centered',
    'client-centric',
    'client-focused',
    'cloud',
    'cloud native',
    'cloudify',
    'collaborat(e|ion|ive)s?',
    'comfort( zone)?',
    'committee',
    'communicat(e|ion)s?',
    'company-employee.fit',
    'compelling',
    'competitive( advantage)?',
    'connected systems?',
    'complex(ity)?',
    'comprehensive',
    'connect the dots',
    'container orchestration',
    'containerizat(e|ion|ing)',
    'content management',
    'contextual(ly)?',
    'contingency plans?',
    'control groups?',
    'control plane',
    'convergence',
    'convergent',
    'conversions?',
    'core business',
    'core competenc(y|ies)',
    'core.to.edge',
    'cosmic',
    'cost-effective',
    'cost/benefit',
    'cost control',
    'craftsmanship',
    'critical path',
    'crypto.currency',
    'crypto(?!graphy).\\w+',
    'crm',
    'cross.sell',
    'crowd.?(fund(s?|ed|ing)|sourc(ed|e|ing))',
    'customer obsession',
    'cutting.edge',
    'cyber',
    'dashboards?',
    'dashboarding',
    'data mining',
    'decentrali(s|z)ed',
    'de-?dupe',
    'deep dive',
    'deep learning',
    'delight',
    'deliverables?',
    'demographic',
    'demystify',
    'demystifying',
    'deployless',
    'devops',
    'digital transformation',
    'discovery',
    'distributed ledgers?',
    'disrupt(ive|tor)?',
    'dollar.productive',
    'downsi(s|z)e',
    'drill down',
    'drink the kool-aid',
    'drop.?in',
    'drop the ball',
    'due dilligence',
    'dynamic(s|ally)?',
    'e-?(business|commerce|tailers)',
    'early.stage',
    'eas(y|ily)',
    'ecosystems?',
    'efficien(t|cy)',
    'effortless(ly)?',
    'elastic',
    'elaboration',
    'elephant in the room',
    'elevator pitch',
    'enabl(e|ing)',
    'emerging markets?',
    'empower(ing|ment|s)?',
    'enablement',
    'end of the day',
    'end.to.end',
    'engulf',
    'engag(e|ing)',
    'enhanced?',
    'enterprise',
    'erp',
    'estimate',
    'eta',
    'etched in stone',
    'evolution',
    'exceed expectations',
    'exclusive(ly)?',
    'exhaustive',
    'expedite',
    'experiences',
    'experts?',
    'expertise',
    'exposure',
    'extraordinary',
    'facilitat(e|or)',
    'fast track',
    'fault.tolerant',
    'first.to.market',
    'flexibility',
    'flux',
    'foot view',
    'forward-thinking',
    'four pillars',
    'frictionless',
    'front lines',
    'frustration[- ]free',
    'functional',
    'futurist',
    'full benefit',
    'future.proof',
    'game changer',
    'game plan',
    'behavioral',
    'global(ly)?',
    'go public',
    'go.to.market',
    'goals?',
    'god-speed',
    'going forward',
    'granular',
    'ground.?breaking',
    'growth',
    'grow',
    'guidance',
    'guru',
    'hackathon',
    'hacker( mindset)?',
    'happiness manage(ment|rs?)',
    'hardball',
    'heavy.lifting',
    'herding cats',
    'hidden.gem',
    'hidden.meaning',
    'high.level',
    '(high|mass).impact',
    'highly.scalable',
    'hive ?mind',
    'hybrid environments?',
    'hyper.personalization',
    'hyperconverged',
    'holistic',
    'impactful',
    'impeccable',
    'in a nutshell',
    'incent',
    'incentivi(s|z)e',
    'increase the odds',
    'incredibl(e|y)',
    '(inflat|redeem)able value',
    'influencers?',
    'influx',
    'innovat(e|ed|ion|ive|ing|or)s?',
    'inspir(e|ing|ation)',
    'insights?',
    'integrat(e|ed|ion)s?',
    'internet of things',
    'intellectual property',
    'intuitive',
    'iot',
    'key results?',
    'kickstart(er|ed)?s?',
    'killjoy',
    'knowledge.(base|transfer|sharing)',
    'kpis?',
    'landing pages?',
    'lead the field',
    'leading',
    'leaders?',
    'leadership',
    'learnings',
    'legacy',
    'lessons learned',
    'level (the )? playing field',
    'level set',
    'leverag(e|ing)',
    'lifecycle',
    'low.hanging fruit',
    'look.(&|and).feel',
    'm2m',
    'machine learning',
    'made simple',
    'magical',
    'market (chang(er|ing)|leader|window|simplified|fit)',
    'market.ready',
    'marketing collateral',
    'maximi(s|z)e',
    'meaningful( client | )interactions?',
    'measurements?',
    'methodolog(y|ies)',
    'metrics',
    'middleware',
    'milestone',
    'military.grade encryption',
    'mind ?share',
    'mind ?shower',
    'mind-boggling',
    'mindset',
    '(mission|time).critical',
    'ml',
    'moneti(s|z)e',
    'mov(e|ing) (fast|forward)',
    'multitask(ing?)',
    'multifaceted',
    'multi-?tenant(ed)?',
    'mvp',
    'negotiated',
    'networking',
    'new.economy',
    'new.breed',
    '(new|next|second).(level|gen|generation)',
    'niches?',
    'ninja',
    'no-brainer',
    'non-traditional management',
    'objectives',
    'occupy the field',
    'off.site',
    'off.the.(radar|shelf)',
    'on board',
    'on.premises?',
    'on the (back end|radar screen|same page|house)',
    'one to one',
    'opportunit(y|ies)',
    'outperform',
    'optimal',
    'orthogonal',
    'outstanding',
    'out(side)?.of.the.(box|loop)',
    'outsourc(e|ed|ing)',
    '(total cost of )?ownership',
    'paradigms?( shift)?',
    'partner(ships?)?',
    'patents?',
    'performance indicators',
    'personaliz(e|ed|ation)',
    'perspective',
    'phases?',
    'phased approach',
    'pipeline',
    'pioneers',
    'pivot',
    'planning horizon',
    'platforms?',
    'plug.?in',
    'potentials?',
    'powerful',
    'prioriti(s|z)ed?',
    'proactive',
    'problem space',
    'processes',
    'profit(ability)?',
    'promotion',
    'promotional collateral',
    'prominent',
    'proprietary',
    'proof.of.concept',
    'purpose.built',
    'push the envelope',
    'push.back',
    'production.ready',
    'productivity',
    'pushing on open doors',
    'quick wins?',
    'rais(e|ing) the bar',
    'ramp.up',
    'ravishing',
    'relationship management',
    'responsive',
    'engage(ments?)?',
    'reach out',
    'reactivation',
    'real.time',
    'real.world',
    'reconfigure',
    'redefin(e|ed|ing)',
    'red flags?',
    'reengineering',
    'reinvent(ing)? the(.square)? wheel',
    'reinvigorate',
    'relevance',
    'repurpose',
    'resilien(ce|cy|t)',
    'resource allocation',
    'restructuring',
    'retention',
    'return on investment',
    'results',
    'reus(e|ability)',
    'revenue',
    'reverse.engineer',
    'revisit',
    'revolution',
    'rich',
    'road ?map',
    'robust',
    'rock.?star',
    'roi',
    'run the numbers',
    '(s|p)aas',
    'sacrific(e|es|ing)',
    'scal(e|es|ing|ability)',
    'high availability',
    'scenarios?',
    'scope',
    'scrum( master)?',
    'seamless',
    'secret sauce',
    'search engine optimization',
    'segments?',
    'self-managed team',
    'seo',
    '(serial )?entrepreneurs?',
    'serverless',
    'service mesh',
    'shareholder value',
    'significant(ly)?',
    'single-source responsibility',
    'skill ?sets?',
    'smart(er)?',
    'smoke (&|and) mirrors',
    'social(.media|.gaming|.networks?)',
    'solidality',
    'solutions?',
    'sophisticated',
    'soup to nuts',
    'sow',
    'spatial.computing',
    'stakeholders?',
    'start.up?',
    'statement of work',
    'state.of.the.art',
    'step.changes?',
    'sticky-?ness',
    'strateg(y|ic|ize|ise)',
    'streamlin(ed|e|ing)',
    'story points?',
    'success(ful)?',
    'super(critical|star|nova)',
    'sustainab(le|ility)',
    'synerg(y|ies|ized|i)',
    'systems?',
    'tailwinds?',
    'talented',
    'take offline',
    'talking points',
    'target (audience|group)',
    'targeted',
    'tasked',
    'tco',
    'team.building',
    'team.player',
    'teamwork',
    'technolog(y|ies)',
    'that being said',
    'throughput',
    'time.to.awesome',
    'time.to.market',
    'timelines?',
    'top.down',
    'top.of.the.game',
    'total quality',
    'touch.base',
    'touchpoints?',
    'traction',
    'transfor(m|ming)',
    'trends?',
    'true',
    'truths?',
    'turnkey',
    'ultimate',
    'up.to.speed',
    'up-?sell',
    'upside',
    'user.friendly',
    'user funnels?',
    'user.experience',
    'utili(s|z)(e|ation)',
    'uncover',
    'unicorn',
    'unique approach',
    'unlimited.holidays',
    'values?',
    'valueable',
    'value.add(ed)?',
    'venture',
    'venturing',
    'vertical market',
    'viral',
    'virtual(ization|isation)?',
    'visibility',
    'visio(n|nary)',
    'walk the talk',
    'wearable',
    'web.enabled',
    'win-win',
    'wisdom of crowds',
    'with due respect',
    'with ease',
    'wizards?',
    'workflows?',
    'workloads?',
    'workplaceless',
    'workspace',
    'world.?class',
    'world a better place',
    'wow.factor',
    'you\'ve never seen (a|an) \\w+',
    'zeitgeist',
];
<commit_msg>add my least favorite business jargon (#127)<commit_after>export default [
    '(business|client|community|culture|customer|data|goal|intelligence|market' +
        '|process|quality|results|role|sales|subject|service|user)' +
        '.(centric(ity)?|facing|oriented|driven|focused|assessment|service|process)',
    '10x',
    '24/7',
    'ai',
    'agile',
    'ambassador',
    'artificial intelligence',
    'at (your|their) fingertips',
    'autonomous',
    'a[-/]b testing',
    'acquisition',
    'action items?',
    'act in time',
    'advantages?',
    'agents?',
    'aggregat(e|ion)',
    'accelerate',
    'all.in.one',
    'all.new',
    'amazing',
    'analytics?',
    'application service providers?',
    'as a service',
    'assets?',
    'astonishing',
    'authoritative',
    'automated',
    'augmented',
    'extended reality',
    'award.winning',
    'b2(b|c)',
    'back to the drawing board',
    'ball.?park',
    'band.aid',
    'bandwidth',
    '(benefit|gap) analysis',
    'bespoke',
    'best.in.class',
    'best.of.breed',
    'best.practice',
    'big.data',
    'big picture',
    'big thinkers?',
    'block.?chain',
    'blazing(ly)? fast',
    'boil the ocean',
    'bottom.line',
    'bottom.up',
    'boost(s|ing)?',
    'brain.?storm(ing)?',
    'brain.?dump',
    'brand(s?|ing|ed)',
    'bright',
    'building.trust',
    'bulletproof',
    'burn.rates?',
    'business( cases| plans)',
    'buzz',
    'call to action',
    'capacity',
    'capabilit(y|ies)',
    'capitali(s|z)e',
    'centers? of excellence',
    'challenges?',
    'change agents?',
    'circle the wagons',
    'client-centered',
    'client-centric',
    'client-focused',
    'cloud',
    'cloud native',
    'cloudify',
    'collaborat(e|ion|ive)s?',
    'comfort( zone)?',
    'committee',
    'communicat(e|ion)s?',
    'company-employee.fit',
    'compelling',
    'competitive( advantage)?',
    'connected systems?',
    'complex(ity)?',
    'comprehensive',
    'connect the dots',
    'container orchestration',
    'containerizat(e|ion|ing)',
    'content management',
    'contextual(ly)?',
    'contingency plans?',
    'control groups?',
    'control plane',
    'convergence',
    'convergent',
    'conversions?',
    'core business',
    'core competenc(y|ies)',
    'core.to.edge',
    'cosmic',
    'cost-effective',
    'cost/benefit',
    'cost control',
    'craftsmanship',
    'critical path',
    'crypto.currency',
    'crypto(?!graphy).\\w+',
    'crm',
    'cross.sell',
    'crowd.?(fund(s?|ed|ing)|sourc(ed|e|ing))',
    'customer obsession',
    'cutting.edge',
    'cyber',
    'dashboards?',
    'dashboarding',
    'data mining',
    'decentrali(s|z)ed',
    'de-?dupe',
    'deep dive',
    'deep learning',
    'delight',
    'deliverables?',
    'demographic',
    'demystify',
    'demystifying',
    'deployless',
    'devops',
    'digital transformation',
    'discovery',
    'distributed ledgers?',
    'disrupt(ive|tor|ion)?',
    'dollar.productive',
    'downsi(s|z)e',
    'drill down',
    'drink the kool-aid',
    'drop.?in',
    'drop the ball',
    'due dilligence',
    'dynamic(s|ally)?',
    'e-?(business|commerce|tailers)',
    'early.stage',
    'eas(y|ily)',
    'ecosystems?',
    'efficien(t|cy)',
    'effortless(ly)?',
    'elastic',
    'elaboration',
    'elephant in the room',
    'elevator pitch',
    'enabl(e|ing)',
    'emerging markets?',
    'empower(ing|ment|s)?',
    'enablement',
    'end of the day',
    'end.to.end',
    'engulf',
    'engag(e|ing)',
    'enhanced?',
    'enterprise',
    'erp',
    'estimate',
    'eta',
    'etched in stone',
    'evolution',
    'exceed expectations',
    'exclusive(ly)?',
    'exhaustive',
    'expedite',
    'experiences',
    'experts?',
    'expertise',
    'exposure',
    'extraordinary',
    'facilitat(e|or)',
    'fast track',
    'fault.tolerant',
    'first.to.market',
    'flexibility',
    'flux',
    'foot view',
    'forward-thinking',
    'four pillars',
    'frictionless',
    'front lines',
    'frustration[- ]free',
    'functional',
    'futurist',
    'full benefit',
    'future.proof',
    'game changer',
    'game plan',
    'behavioral',
    'global(ly)?',
    'go public',
    'go.to.market',
    'goals?',
    'god-speed',
    'going forward',
    'granular',
    'ground.?breaking',
    'growth',
    'grow',
    'guidance',
    'guru',
    'hackathon',
    'hacker( mindset)?',
    'happiness manage(ment|rs?)',
    'hardball',
    'heavy.lifting',
    'herding cats',
    'hidden.gem',
    'hidden.meaning',
    'high.level',
    '(high|mass).impact',
    'highly.scalable',
    'hive ?mind',
    'hybrid environments?',
    'hyper.personalization',
    'hyperconverged',
    'holistic',
    'impactful',
    'impeccable',
    'in a nutshell',
    'incent',
    'incentivi(s|z)e',
    'increase the odds',
    'incredibl(e|y)',
    '(inflat|redeem)able value',
    'influencers?',
    'influx',
    'innovat(e|ed|ion|ive|ing|or)s?',
    'inspir(e|ing|ation)',
    'insights?',
    'integrat(e|ed|ion)s?',
    'internet of things',
    'intellectual property',
    'intuitive',
    'iot',
    'key results?',
    'kickstart(er|ed)?s?',
    'killjoy',
    'knowledge.(base|transfer|sharing)',
    'kpis?',
    'landing pages?',
    'lead the field',
    'leading',
    'leaders?',
    'leadership',
    'learnings',
    'legacy',
    'lessons learned',
    'level (the )? playing field',
    'level set',
    'leverag(e|ing)',
    'lifecycle',
    'low.hanging fruit',
    'look.(&|and).feel',
    'm2m',
    'machine learning',
    'made simple',
    'magical',
    'market (chang(er|ing)|leader|window|simplified|fit)',
    'market.ready',
    'marketing collateral',
    'maximi(s|z)e',
    'meaningful( client | )interactions?',
    'measurements?',
    'methodolog(y|ies)',
    'metrics',
    'middleware',
    'milestone',
    'military.grade encryption',
    'mind ?share',
    'mind ?shower',
    'mind-boggling',
    'mindset',
    '(mission|time).critical',
    'ml',
    'moneti(s|z)e',
    'mov(e|ing) (fast|forward)',
    'multitask(ing?)',
    'multifaceted',
    'multi-?tenant(ed)?',
    'mvp',
    'negotiated',
    'networking',
    'new.economy',
    'new.breed',
    '(new|next|second).(level|gen|generation)',
    'niches?',
    'ninja',
    'no-brainer',
    'non-traditional management',
    'objectives',
    'occupy the field',
    'off.site',
    'off.the.(radar|shelf)',
    'on board',
    'on.premises?',
    'on the (back end|radar screen|same page|house)',
    'one to one',
    'open the kimono',
    'opportunit(y|ies)',
    'outperform',
    'optimal',
    'orthogonal',
    'outstanding',
    'out(side)?.of.the.(box|loop)',
    'outsourc(e|ed|ing)',
    '(total cost of )?ownership',
    'paradigms?( shift)?',
    'partner(ships?)?',
    'patents?',
    'performance indicators',
    'personaliz(e|ed|ation)',
    'perspective',
    'phases?',
    'phased approach',
    'pipeline',
    'pioneers',
    'pivot',
    'planning horizon',
    'platforms?',
    'plug.?in',
    'potentials?',
    'powerful',
    'prioriti(s|z)ed?',
    'proactive',
    'problem space',
    'processes',
    'profit(ability)?',
    'promotion',
    'promotional collateral',
    'prominent',
    'proprietary',
    'proof.of.concept',
    'purpose.built',
    'push the envelope',
    'push.back',
    'production.ready',
    'productivity',
    'pushing on open doors',
    'quick wins?',
    'rais(e|ing) the bar',
    'ramp.up',
    'ravishing',
    'relationship management',
    'responsive',
    'engage(ments?)?',
    'reach out',
    'reactivation',
    'real.time',
    'real.world',
    'reconfigure',
    'redefin(e|ed|ing)',
    'red flags?',
    'reengineering',
    'reinvent(ing)? the(.square)? wheel',
    'reinvigorate',
    'relevance',
    'repurpose',
    'resilien(ce|cy|t)',
    'resource allocation',
    'restructuring',
    'retention',
    'return on investment',
    'results',
    'reus(e|ability)',
    'revenue',
    'reverse.engineer',
    'revisit',
    'revolution',
    'rich',
    'road ?map',
    'robust',
    'rock.?star',
    'roi',
    'run the numbers',
    '(s|p)aas',
    'sacrific(e|es|ing)',
    'scal(e|es|ing|ability)',
    'high availability',
    'scenarios?',
    'scope',
    'scrum( master)?',
    'seamless',
    'secret sauce',
    'search engine optimization',
    'segments?',
    'self-managed team',
    'seo',
    '(serial )?entrepreneurs?',
    'serverless',
    'service mesh',
    'shareholder value',
    'significant(ly)?',
    'single-source responsibility',
    'skill ?sets?',
    'smart(er)?',
    'smoke (&|and) mirrors',
    'social(.media|.gaming|.networks?)',
    'solidality',
    'solutions?',
    'sophisticated',
    'soup to nuts',
    'sow',
    'spatial.computing',
    'stakeholders?',
    'start.up?',
    'statement of work',
    'state.of.the.art',
    'step.changes?',
    'sticky-?ness',
    'strateg(y|ic|ize|ise)',
    'streamlin(ed|e|ing)',
    'story points?',
    'success(ful)?',
    'super(critical|star|nova)',
    'sustainab(le|ility)',
    'synerg(y|ies|ized|i)',
    'systems?',
    'tailwinds?',
    'talented',
    'take offline',
    'talking points',
    'target (audience|group)',
    'targeted',
    'tasked',
    'tco',
    'team.building',
    'team.player',
    'teamwork',
    'technolog(y|ies)',
    'that being said',
    'throughput',
    'time.to.awesome',
    'time.to.market',
    'timelines?',
    'top.down',
    'top.of.the.game',
    'total quality',
    'touch.base',
    'touchpoints?',
    'traction',
    'transfor(m|ming)',
    'trends?',
    'true',
    'truths?',
    'turnkey',
    'ultimate',
    'up.to.speed',
    'up-?sell',
    'upside',
    'user.friendly',
    'user funnels?',
    'user.experience',
    'utili(s|z)(e|ation)',
    'uncover',
    'unicorn',
    'unique approach',
    'unlimited.holidays',
    'values?',
    'valueable',
    'value.add(ed)?',
    'venture',
    'venturing',
    'vertical market',
    'viral',
    'virtual(ization|isation)?',
    'visibility',
    'visio(n|nary)',
    'walk the talk',
    'wearable',
    'web.enabled',
    'win-win',
    'wisdom of crowds',
    'with due respect',
    'with ease',
    'wizards?',
    'workflows?',
    'workloads?',
    'workplaceless',
    'workspace',
    'world.?class',
    'world a better place',
    'wow.factor',
    'you\'ve never seen (a|an) \\w+',
    'zeitgeist',
];
<|endoftext|>


<commit_before>(function($) {
   var state, timer;
   if(!document.createTouch) {
      console.log("Your browser does not support touch on this device");
      return;
   }
   state = {};

   function movement(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2;
      return Math.abs(dx) > 30 || Math.abs(dy) > 30 ? {x: dx, y: dy} : null;
   }

   function direction(delta) {
      var x = delta.x, y = delta.y;
   }

   function ontouch(te) {
      var touch, now, elapsed, target = te.target, type = te.type, mov, tgt;
      switch(type) {
         case "touchstart":
            touch = te.touches[0];
            now = Date.now();
            elapsed = now - (state.last || now);

            if(elapsed > 0 && elapsed < 250 && state.target === target) {
               state.dbltap = true;
            }else {
               state.x = touch.screenX;
               state.y = touch.screenY;
               state.last = now;
               state.target = target;
               timer = setTimeout(function() {
                  if(state.moved) {
                     return;
                  }
                  state.taphold = true;
                  te.preventDefault();
                  $(target).dispatch("taphold");
               }, 750);
            }
            break;
         case "touchmove":
            touch = te.changedTouches[0];
            state.moved = movement(touch.screenX, touch.screenY, state.x, state.y);
            break;
         case "touchend":
            if(state.taphold) {
               delete state.taphold;
               return;
            }
            clearTimeout(timer);
            touch = te.changedTouches[0];
            mov = state.moved;
            tgt = $(target);
            if(mov) {
               tgt.dispatch("swipe");
               delete state.moved;
            }else {
               tgt.dispatch("tap");

               if(state.dbltap) {
                  delete state.last;
                  delete state.dbltap;
                  if(state.target === target) {
                     tgt.dispatch("dbltap");
                     return;
                  }
               }
            }
            break;
         case "touchcancel":
            clearTimeout(timer);
            break;
      }
   }

   $.defineEvent({
      setup: function() {
         $(document.body).on("touchstart", ontouch)
            .on("touchmove", ontouch)
            .on("touchend", ontouch)
            .on("touchcancel", ontouch);
      },
      destroy: function() {
         $(document.body).un("touchstart", ontouch)
            .un("touchmove", ontouch)
            .un("touchend", ontouch)
            .un("touchcancel", ontouch);
      }
   });
})(h5);
<commit_msg>fixed tap and swipe events behaviour. e.g. don't fire in case of multi-finger gusters<commit_after>/**
 * Defines custom events for touch related gusters.
 * Following events are defined:
 * tap, dbltap, taphold, swipe, swipeleft, swiperight
 * @author anaik
 */
(function($) {
   var state = {}, timer;

   /**
    * Calculate the delta difference between two points (x1,y1) and (x2,y2)
    * @return A delta object {x: xdelta, y: ydelta} if the difference is more
    * than 30 pixels or null if its less. The values x and y can be -ve
    */
   function movement(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2, xa, ya;
      if((xa = Math.abs(dx)) < 30 & (ya = Math.abs(dy)) < 30) {
         return null;
      }
      return {
         x: dx,
         y: dy,
         dir: xa >= ya ? (dx < 0 ? "left" : "right") : (dy < 0 ? "up" : "down")
      };
   }

   function ontouch(te) {
      var now, elapsed, touches = te.touches, cTouches = te.changedTouches, touch, target = te.target,
         type = te.type, distance, tar;

      // bail out if we have more than one touches
      if(touches.length > 1 || cTouches.length > 1) {
         state = {};
         return;
      }

      switch(type) {
         case "touchstart":
            touch = touches[0];
            now = Date.now();
            elapsed = now - (state.last || now);
            if(elapsed > 0 && elapsed < 250 && state.target === target) {
               state.dbltap = true;
            }else {
               state.last = now;
               state.x = touch.screenX;
               state.y = touch.screenY;
               state.target = target;
               timer = setTimeout(function() {
                  if(state.moved) {
                     return;
                  }
                  state.wastaphold = true;
                  $(target).dispatch("taphold");
               }, 750);
            }
            break;
         case "touchmove":
            if(!state.last) {
               return;
            }
            touch = cTouches[0];
            state.distance = movement(touch.screenX, touch.screenY, state.x, state.y);
            if(state.distance) {
               state.moved = true;
            }
            break;
         case "touchend":
            clearTimeout(timer);
            touch = cTouches[0];
            // check if the taphold event fired
            if(state.wastaphold || !state.last) {
               state.wastaphold = false;
               return;
            }

            // check for swipe events
            distance = state.distance;
            tar = $(target);
            if(distance) {
               tar.dispatch("swipe").dispatch("swipe" + distance.dir);
               state.x = state.y = state.distance = state.moved = null;
            }else {
               tar.dispatch("tap");
               if(state.dbltap) {
                  state.last = state.dbltap = false;
                  if(state.target === target) {
                     tar.dispatch("dbltap");
                  }
               }
            }
            break;
         default:
            break;
      }
   }

   $.defineEvent({
      setup: function() {
         $(document).on("touchstart", ontouch)
            .on("touchmove", ontouch)
            .on("touchend", ontouch)
            .on("touchcancel", ontouch);
      },
      destroy: function() {
         $(document).un("touchstart", ontouch)
            .un("touchmove", ontouch)
            .un("touchend", ontouch)
            .un("touchcancel", ontouch);
      }
   });
})(h5);

<|endoftext|>


<commit_before>/**
 * Jdigi
 *
 * Copyright 2014, Bob Jamison
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var Constants = require('./digi').Constants;

/**
 * Provides a Waterfall display and tuning interactivity
 * @param par the parent Digi of this waterfall
 * @canvas the canvas to use for drawing
 */
function Tuner(par, canvas) {
    "use strict";

    var self = this;

    window.requestAnimationFrame =
        window.requestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame;

    var BINS = Constants.BINS;

    var MAX_FREQ = par.getSampleRate() * 0.5;

    var frequency = 1000;

    //note that this is different from the public method
    function setFrequency(freq) {
        frequency = freq;
        par.setFrequency(freq);
    }

    function trace(msg) {
        if (typeof console !== "undefined")
            console.log("Tuner: " + msg);
    }
    function error(msg) {
        if (typeof console !== "undefined")
            console.log("Tuner error : " + msg);
    }

    function createIndices(targetsize, sourcesize) {
        var xs = new Array(targetsize);
        var ratio = sourcesize / targetsize;
        for (var i=0 ; i < targetsize ; i++) {
            xs[i] = Math.floor(i * ratio);
        }
        return xs;
    }

    var indices, width, height, ctx, imgData, imglen, buf8, rowsize, lastRow;

    function resize() {
 	     width   = canvas.width;
	      height  = canvas.height;
        indices = createIndices(width, BINS);
        ctx     = canvas.getContext('2d');
        imgData = ctx.createImageData(width, height);
        imglen  = imgData.data.length;
        buf8    = new Uint8ClampedArray(imglen);
    		for (var i=0 ; i < imglen ; ) {
		      	buf8[i++] = 0;
			      buf8[i++] = 0;
			      buf8[i++] = 0;
			      buf8[i++] = 255;
		    }
        imgData.data.set(buf8);
        ctx.putImageData(imgData, 0, 0);
        rowsize  = imglen / height;
        lastRow  = imglen - rowsize;
    }

    resize();

	canvas.setAttribute("tabindex", "1");

    //####################################################################
    //#   MOUSE and KEY EVENTS
    //####################################################################

    var dragging        = false;
    canvas.onclick      = function(event) { mouseFreq(event); };
    canvas.onmousedown  = function(event) { dragging=true; };
    canvas.onmouseup    = function(event) { dragging=false; };
    canvas.onmousemove  = function(event) { if (dragging) mouseFreq(event); };
    canvas.onkeydown    = handleKey;
    canvas.onmousewheel = handleWheel;
    canvas.addEventListener("DOMMouseScroll", handleWheel, false);

    function mouseFreq(event) {
        var pt = getMousePos(canvas, event);
        //trace("point: " + pt.x + ":" + pt.y);
        var freq = MAX_FREQ * pt.x / width;
        //trace("freq:" + freq);
        setFrequency(freq);
    }

    function getMousePos(canvas, evt) {
        var rect = canvas.getBoundingClientRect();
        return {x: evt.clientX - rect.left, y: evt.clientY - rect.top};
    }

    function handleWheel(evt) {
        var delta = (evt.detail < 0 || evt.wheelDelta > 0) ? 1 : -1;
        setFrequency(frequency + delta * 1); //or other increments here
        evt.preventDefault();
    }

    //fine tuning, + or - one hertz
    function handleKey(evt) {
        var key = evt.which;
        if (key===37 || key===40) {
            setFrequency(frequency - 1);
        } else if (key===38 || key===39) {
            setFrequency(frequency + 1);
        }
        evt.preventDefault();
    }

    //####################################################################
    //#  R E N D E R I N G
    //####################################################################

    /**
     * Make a palette. tweak this often
     * TODO:  consider using an HSV heat map
     */
    function makePalette() {
        var xs = new Array(256);
        for (var i = 0 ; i < 256 ; i++) {
            var r = (i < 170) ? 0 : (i-170) * 3;
            var g = (i <  85) ? 0 : (i < 170) ? (i-85) * 3 : 255;
            var b = (i <  85) ? i * 3 : 255;
            var col = [ r, g, b, 255 ];
            xs[i] = col;
        }
        return xs;
    }

    var palette = makePalette();

    function drawSpectrum(data) {
        var x, y, v;

        //ctx.fillStyle = 'red';
        ctx.fillStyle = 'rgba(255, 255, 255, 0.50)';
        //ctx.lineWidth = 1;
        ctx.beginPath();
        var base = height>>1; //move this around
        ctx.moveTo(0, base);
        var log = Math.log;
        for (x=0; x<width ; x++) {
            v = log(1.0 + data[indices[x]]) * 12.0;
            y = base - v;
            //trace("x:" + x + " y:" + y);
            ctx.lineTo(x, y);
        }
        ctx.lineTo(width-1,base);
        for (x=width-1; x>=0 ; x--) {
            v = log(1.0 + data[indices[x]]) * 12.0;
            y = base + v;
            //trace("x:" + x + " y:" + y);
            ctx.lineTo(x, y);
        }
        ctx.lineTo(0,base);
        ctx.closePath();
        //var bbox = ctx.getBBox();
        ctx.fill();
    }

    function drawWaterfall(data) {
        buf8.set(buf8.subarray(rowsize, imglen)); //<-cool, if this works
        //trace("data:" + data[50]);

        var idx = lastRow;
        for (var x=0; x<width ; x++) {
            var v = data[indices[x]];
            var pix = palette[v & 255];
            //if (x==50)trace("p:" + p + "  pix:" + pix.toString(16));
            buf8[idx++] = pix[0];
            buf8[idx++] = pix[1];
            buf8[idx++] = pix[2];
            buf8[idx++] = pix[3];
        }
        imgData.data.set(buf8);
        ctx.putImageData(imgData, 0, 0);
    }

    function drawWaterfall2(data) {

        buf8.set(buf8.subarray(rowsize, imglen)); //<-cool, if this works
        var idx = lastRow;
        var abs = Math.abs;
        var log = Math.log;
        for (var x=0; x<width ; x++) {
            var v = abs(data[indices[x]]);
            //if (x==50) trace("v:" + v);
            var p = log(1.0 + v) * 30;
            //if (x==50)trace("x:" + x + " p:" + p);
            var pix = palette[p & 255];
            //if (x==50)trace("p:" + p + "  pix:" + pix.toString(16));
            buf8[idx++] = pix[0];
            buf8[idx++] = pix[1];
            buf8[idx++] = pix[2];
            buf8[idx++] = pix[3];
        }
        imgData.data.set(buf8);
        ctx.putImageData(imgData, 0, 0);
    }

    function drawTuner() {
        var pixPerHz = 1 / MAX_FREQ * width;

        var x    = frequency * pixPerHz;
        var bw   = par.getBandwidth();
        var bww  = bw * pixPerHz;
        var bwlo = (frequency - bw * 0.5) * pixPerHz;

        ctx.fillStyle = "rgba(255,255,255,0.25)";
        ctx.fillRect(bwlo, 0, bww, height);
        ctx.strokeStyle = "red";
        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x, height);
        ctx.stroke();

        var top = height-15;

        for (var hz=0 ; hz < MAX_FREQ ; hz+=100) {
            if ((hz % 1000) === 0) {
                ctx.strokeStyle = "red";
                ctx.beginPath();
                x = hz * pixPerHz;
                ctx.moveTo(x, top);
                ctx.lineTo(x, height);
                ctx.stroke();
            } else {
                ctx.strokeStyle = "white";
                ctx.beginPath();
                x = hz * pixPerHz;
                ctx.moveTo(x, top+10);
                ctx.lineTo(x, height);
                ctx.stroke();
            }
        }

        ctx.fillStyle = "gray";
        for (hz=0 ; hz < MAX_FREQ ; hz+=500) {
            x = hz * pixPerHz - 10;
            ctx.fillText(hz.toString(),x,top+14);
        }
    }

    var _scopeData = [];

    /**
     * Plot mode-specific decoder graph data.
     * This method expects the data to be an array of [x,y] coordinates,
     * with x and y ranging from -1.0 to 1.0.  It is up to the mode generating
     * this array to determine how to draw it, and what it means.
     */
    function drawScope() {
        var boxW   = 100;
        var boxH   = 100;
        var boxX   = width - boxW;
        var boxY   = 0;
        var centerX = boxX + (boxW>>1) ;
        var centerY = boxY + (boxH>>1) ;

        ctx.save();
        ctx.beginPath();
        ctx.strokeStyle = "white";
        ctx.rect(boxX, boxY, boxW, boxH);
        ctx.stroke();
        ctx.clip();

        ctx.beginPath();
        ctx.moveTo(centerX, boxY);
        ctx.lineTo(centerX, boxY + boxH);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(boxX, centerY);
        ctx.lineTo(boxX + boxW, centerY);
        ctx.stroke();

        ctx.strokeStyle = "yellow";
        ctx.beginPath();
        var pt = _scopeData[0];
        var x = centerX + pt[0] * 50.0;
        var y = centerY + pt[1] * 50.0;
        ctx.moveTo(x,y);
        var len = _scopeData.length;
        for (var i=1 ; i<len ; i++) {
            pt = _scopeData[i];
            x = centerX + pt[0] * 50.0;
            y = centerY + pt[1] * 50.0;
            //console.log("pt:" + x + ":" + y);
            ctx.lineTo(x,y);
        }
        ctx.stroke();

        //all done
        ctx.restore();
    }

    function update(data) {
        drawWaterfall2(data);
        drawSpectrum(data);
        drawTuner();
        drawScope();
    }

    //####################################################################
    //# P U B L I C    M E T H O D S
    //####################################################################

    this.setFrequency = function(freq) {
        frequency = freq;
    };

   this.showScope = function(data) {
        _scopeData = data;
    };

    this.update = function(data) {
		requestAnimationFrame(function() { update(data); } );
    };

} //Tuner

module.exports.Tuner = Tuner;
<commit_msg>Nasty tabs<commit_after>/**
 * Jdigi
 *
 * Copyright 2014, Bob Jamison
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var Constants = require('./digi').Constants;

/**
 * Provides a Waterfall display and tuning interactivity
 * @param par the parent Digi of this waterfall
 * @canvas the canvas to use for drawing
 */
function Tuner(par, canvas) {
    "use strict";

    var self = this;

    window.requestAnimationFrame =
        window.requestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame;

    var BINS = Constants.BINS;

    var MAX_FREQ = par.getSampleRate() * 0.5;

    var frequency = 1000;

    //note that this is different from the public method
    function setFrequency(freq) {
        frequency = freq;
        par.setFrequency(freq);
    }

    function trace(msg) {
        if (typeof console !== "undefined")
            console.log("Tuner: " + msg);
    }
    function error(msg) {
        if (typeof console !== "undefined")
            console.log("Tuner error : " + msg);
    }

    function createIndices(targetsize, sourcesize) {
        var xs = new Array(targetsize);
        var ratio = sourcesize / targetsize;
        for (var i=0 ; i < targetsize ; i++) {
            xs[i] = Math.floor(i * ratio);
        }
        return xs;
    }

    var indices, width, height, ctx, imgData, imglen, buf8, rowsize, lastRow;

    function resize() {
        width   = canvas.width;
        height  = canvas.height;
        indices = createIndices(width, BINS);
        ctx     = canvas.getContext('2d');
        imgData = ctx.createImageData(width, height);
        imglen  = imgData.data.length;
        buf8    = new Uint8ClampedArray(imglen);
        for (var i=0 ; i < imglen ; ) {
            buf8[i++] = 0;
            buf8[i++] = 0;
            buf8[i++] = 0;
            buf8[i++] = 255;
        }
        imgData.data.set(buf8);
        ctx.putImageData(imgData, 0, 0);
        rowsize  = imglen / height;
        lastRow  = imglen - rowsize;
    }

    resize();

    canvas.setAttribute("tabindex", "1");

    //####################################################################
    //#   MOUSE and KEY EVENTS
    //####################################################################

    var dragging        = false;
    canvas.onclick      = function(event) { mouseFreq(event); };
    canvas.onmousedown  = function(event) { dragging=true; };
    canvas.onmouseup    = function(event) { dragging=false; };
    canvas.onmousemove  = function(event) { if (dragging) mouseFreq(event); };
    canvas.onkeydown    = handleKey;
    canvas.onmousewheel = handleWheel;
    canvas.addEventListener("DOMMouseScroll", handleWheel, false);

    function mouseFreq(event) {
        var pt = getMousePos(canvas, event);
        var freq = MAX_FREQ * pt.x / width;
        setFrequency(freq);
    }

    function getMousePos(canvas, evt) {
        var rect = canvas.getBoundingClientRect();
        return {x: evt.clientX - rect.left, y: evt.clientY - rect.top};
    }

    function handleWheel(evt) {
        var delta = (evt.detail < 0 || evt.wheelDelta > 0) ? 1 : -1;
        setFrequency(frequency + delta * 1); //or other increments here
        evt.preventDefault();
    }

    //fine tuning, + or - one hertz
    function handleKey(evt) {
        var key = evt.which;
        if (key===37 || key===40) {
            setFrequency(frequency - 1);
        } else if (key===38 || key===39) {
            setFrequency(frequency + 1);
        }
        evt.preventDefault();
    }

    //####################################################################
    //#  R E N D E R I N G
    //####################################################################

    /**
     * Make a palette. tweak this often
     * TODO:  consider using an HSV heat map
     */
    function makePalette() {
        var xs = new Array(256);
        for (var i = 0 ; i < 256 ; i++) {
            var r = (i < 170) ? 0 : (i-170) * 3;
            var g = (i <  85) ? 0 : (i < 170) ? (i-85) * 3 : 255;
            var b = (i <  85) ? i * 3 : 255;
            var col = [ r, g, b, 255 ];
            xs[i] = col;
        }
        return xs;
    }

    var palette = makePalette();

    function drawSpectrum(data) {
        var x, y, v;

        //ctx.fillStyle = 'red';
        ctx.fillStyle = 'rgba(255, 255, 255, 0.50)';
        //ctx.lineWidth = 1;
        ctx.beginPath();
        var base = height>>1; //move this around
        ctx.moveTo(0, base);
        var log = Math.log;
        for (x=0; x<width ; x++) {
            v = log(1.0 + data[indices[x]]) * 12.0;
            y = base - v;
            //trace("x:" + x + " y:" + y);
            ctx.lineTo(x, y);
        }
        ctx.lineTo(width-1,base);
        for (x=width-1; x>=0 ; x--) {
            v = log(1.0 + data[indices[x]]) * 12.0;
            y = base + v;
            //trace("x:" + x + " y:" + y);
            ctx.lineTo(x, y);
        }
        ctx.lineTo(0,base);
        ctx.closePath();
        //var bbox = ctx.getBBox();
        ctx.fill();
    }

    function drawWaterfall(data) {
        buf8.set(buf8.subarray(rowsize, imglen)); //<-cool, if this works
        //trace("data:" + data[50]);

        var idx = lastRow;
        for (var x=0; x<width ; x++) {
            var v = data[indices[x]];
            var pix = palette[v & 255];
            //if (x==50)trace("p:" + p + "  pix:" + pix.toString(16));
            buf8[idx++] = pix[0];
            buf8[idx++] = pix[1];
            buf8[idx++] = pix[2];
            buf8[idx++] = pix[3];
        }
        imgData.data.set(buf8);
        ctx.putImageData(imgData, 0, 0);
    }

    function drawWaterfall2(data) {

        buf8.set(buf8.subarray(rowsize, imglen)); //<-cool, if this works
        var idx = lastRow;
        var abs = Math.abs;
        var log = Math.log;
        for (var x=0; x<width ; x++) {
            var v = abs(data[indices[x]]);
            //if (x==50) trace("v:" + v);
            var p = log(1.0 + v) * 30;
            //if (x==50)trace("x:" + x + " p:" + p);
            var pix = palette[p & 255];
            //if (x==50)trace("p:" + p + "  pix:" + pix.toString(16));
            buf8[idx++] = pix[0];
            buf8[idx++] = pix[1];
            buf8[idx++] = pix[2];
            buf8[idx++] = pix[3];
        }
        imgData.data.set(buf8);
        ctx.putImageData(imgData, 0, 0);
    }

    function drawTuner() {
        var pixPerHz = 1 / MAX_FREQ * width;

        var x    = frequency * pixPerHz;
        var bw   = par.getBandwidth();
        var bww  = bw * pixPerHz;
        var bwlo = (frequency - bw * 0.5) * pixPerHz;

        ctx.fillStyle = "rgba(255,255,255,0.25)";
        ctx.fillRect(bwlo, 0, bww, height);
        ctx.strokeStyle = "red";
        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x, height);
        ctx.stroke();

        var top = height-15;

        for (var hz=0 ; hz < MAX_FREQ ; hz+=100) {
            if ((hz % 1000) === 0) {
                ctx.strokeStyle = "red";
                ctx.beginPath();
                x = hz * pixPerHz;
                ctx.moveTo(x, top);
                ctx.lineTo(x, height);
                ctx.stroke();
            } else {
                ctx.strokeStyle = "white";
                ctx.beginPath();
                x = hz * pixPerHz;
                ctx.moveTo(x, top+10);
                ctx.lineTo(x, height);
                ctx.stroke();
            }
        }

        ctx.fillStyle = "gray";
        for (hz=0 ; hz < MAX_FREQ ; hz+=500) {
            x = hz * pixPerHz - 10;
            ctx.fillText(hz.toString(),x,top+14);
        }
    }

    var _scopeData = [];

    /**
     * Plot mode-specific decoder graph data.
     * This method expects the data to be an array of [x,y] coordinates,
     * with x and y ranging from -1.0 to 1.0.  It is up to the mode generating
     * this array to determine how to draw it, and what it means.
     */
    function drawScope() {
        var boxW   = 100;
        var boxH   = 100;
        var boxX   = width - boxW;
        var boxY   = 0;
        var centerX = boxX + (boxW>>1) ;
        var centerY = boxY + (boxH>>1) ;

        ctx.save();
        ctx.beginPath();
        ctx.strokeStyle = "white";
        ctx.rect(boxX, boxY, boxW, boxH);
        ctx.stroke();
        ctx.clip();

        ctx.beginPath();
        ctx.moveTo(centerX, boxY);
        ctx.lineTo(centerX, boxY + boxH);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(boxX, centerY);
        ctx.lineTo(boxX + boxW, centerY);
        ctx.stroke();

        ctx.strokeStyle = "yellow";
        ctx.beginPath();
        var pt = _scopeData[0];
        var x = centerX + pt[0] * 50.0;
        var y = centerY + pt[1] * 50.0;
        ctx.moveTo(x,y);
        var len = _scopeData.length;
        for (var i=1 ; i<len ; i++) {
            pt = _scopeData[i];
            x = centerX + pt[0] * 50.0;
            y = centerY + pt[1] * 50.0;
            //console.log("pt:" + x + ":" + y);
            ctx.lineTo(x,y);
        }
        ctx.stroke();

        //all done
        ctx.restore();
    }

    function update(data) {
        drawWaterfall2(data);
        drawSpectrum(data);
        drawTuner();
        drawScope();
    }

    //####################################################################
    //# P U B L I C    M E T H O D S
    //####################################################################

    this.setFrequency = function(freq) {
        frequency = freq;
    };

   this.showScope = function(data) {
        _scopeData = data;
    };

    this.update = function(data) {
        requestAnimationFrame(function() { update(data); } );
    };

} //Tuner

module.exports.Tuner = Tuner;
<|endoftext|>


<commit_before>import { trackEvent } from './analytics';

import { computeHtml, computeCss, computeJs } from './computes';
import { JsModes } from './codeModes';
import { deferred } from './deferred';
const esprima = require('esprima');

window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
window.$ = document.querySelector.bind(document);

window.chrome = window.chrome || {};
window.chrome.i18n = {
	getMessage: () => {}
};

window.$all = selector => [...document.querySelectorAll(selector)];
window.IS_EXTENSION = !!window.chrome.extension;
export const BASE_PATH =
	window.chrome.extension ||
	window.DEBUG ||
	process.env.NODE_ENV == 'development'
		? '/'
		: '/app';

var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

/**
 * The following 2 functions are supposed to find the next/previous sibling until the
 * passed `selector` is matched. But for now it actually finds the next/previous
 * element of `this` element in the list of `selector` matched element inside `this`'s
 * parent.
 * @param  Selector that should match for next siblings
 * @return element Next element that mathes `selector`
 */
Node.prototype.nextUntil = function(selector) {
	const siblings = Array.from(this.parentNode.querySelectorAll(selector));
	const index = siblings.indexOf(this);
	return siblings[index + 1];
};

/*
 * @param  Selector that should match for next siblings
 * @return element Next element that mathes `selector`
 */
Node.prototype.previousUntil = function(selector) {
	const siblings = Array.from(this.parentNode.querySelectorAll(selector));
	const index = siblings.indexOf(this);
	return siblings[index - 1];
};

// Safari doesn't have this!
window.requestIdleCallback =
	window.requestIdleCallback ||
	function(fn) {
		setTimeout(fn, 10);
	};

// https://github.com/substack/semver-compare/blob/master/index.js
export function semverCompare(a, b) {
	var pa = a.split('.');
	var pb = b.split('.');
	for (var i = 0; i < 3; i++) {
		var na = Number(pa[i]);
		var nb = Number(pb[i]);
		if (na > nb) {
			return 1;
		}
		if (nb > na) {
			return -1;
		}
		if (!isNaN(na) && isNaN(nb)) {
			return 1;
		}
		if (isNaN(na) && !isNaN(nb)) {
			return -1;
		}
	}
	return 0;
}

export function generateRandomId(len) {
	var length = len || 10;
	var id = '';
	for (var i = length; i--; ) {
		id += alphaNum[~~(Math.random() * alphaNum.length)];
	}
	return id;
}

export function onButtonClick(btn, listener) {
	btn.addEventListener('click', function buttonClickListener(e) {
		listener(e);
		return false;
	});
}

export function log() {
	if (window.DEBUG) {
		console.log(Date.now(), ...arguments);
	}
}

/**
 * Adds timed limit on the loops found in the passed code.
 * Contributed by Ariya Hidayat!
 * @param code {string}	Code to be protected from infinite loops.
 */
export function addInfiniteLoopProtection(code, { timeout }) {
	var loopId = 1;
	var patches = [];
	var varPrefix = '_wmloopvar';
	var varStr = 'var %d = Date.now();\n';
	var checkStr = `\nif (Date.now() - %d > ${timeout}) { window.top.previewException(new Error("Infinite loop")); break;}\n`;

	esprima.parse(
		code,
		{
			tolerant: true,
			range: true,
			jsx: true
		},
		function(node) {
			switch (node.type) {
				case 'DoWhileStatement':
				case 'ForStatement':
				case 'ForInStatement':
				case 'ForOfStatement':
				case 'WhileStatement':
					var start = 1 + node.body.range[0];
					var end = node.body.range[1];
					var prolog = checkStr.replace('%d', varPrefix + loopId);
					var epilog = '';

					if (node.body.type !== 'BlockStatement') {
						// `while(1) doThat()` becomes `while(1) {doThat()}`
						prolog = '{' + prolog;
						epilog = '}';
						--start;
					}

					patches.push({
						pos: start,
						str: prolog
					});
					patches.push({
						pos: end,
						str: epilog
					});
					patches.push({
						pos: node.range[0],
						str: varStr.replace('%d', varPrefix + loopId)
					});
					++loopId;
					break;

				default:
					break;
			}
		}
	);

	/* eslint-disable no-param-reassign */
	patches
		.sort(function(a, b) {
			return b.pos - a.pos;
		})
		.forEach(function(patch) {
			code = code.slice(0, patch.pos) + patch.str + code.slice(patch.pos);
		});

	/* eslint-disable no-param-reassign */
	return code;
}

export function getHumanDate(timestamp) {
	var d = new Date(timestamp);
	var retVal =
		d.getDate() +
		' ' +
		[
			'January',
			'February',
			'March',
			'April',
			'May',
			'June',
			'July',
			'August',
			'September',
			'October',
			'November',
			'December'
		][d.getMonth()] +
		' ' +
		d.getFullYear();
	return retVal;
}

// create a one-time event
export function once(node, type, callback) {
	// create event
	node.addEventListener(type, function(e) {
		// remove event
		e.target.removeEventListener(type, arguments.callee);
		// call handler
		return callback(e);
	});
}

export function downloadFile(fileName, blob) {
	function downloadWithAnchor() {
		var a = document.createElement('a');
		a.href = window.URL.createObjectURL(blob);
		a.download = fileName;
		a.style.display = 'none';
		document.body.appendChild(a);
		a.click();
		a.remove();
	}

	// HACK: because chrome.downloads isn't working on optional permissions
	// anymore.
	downloadWithAnchor();

	/* if (false && window.IS_EXTENSION) {
		chrome.downloads.download({
				url: window.URL.createObjectURL(blob),
				filename: fileName,
				saveAs: true
			},
			() => {
				// If there was an error, just download the file using ANCHOR method.
				if (chrome.runtime.lastError) {
					downloadWithAnchor();
				}
			}
		);
	} else {
		downloadWithAnchor();
	} */
}

export function writeFile(name, blob, cb) {
	var fileWritten = false;

	function getErrorHandler(type) {
		return function() {
			log(arguments);
			trackEvent('fn', 'error', type);
			// When there are too many write errors, show a message.
			writeFile.errorCount = (writeFile.errorCount || 0) + 1;
			if (writeFile.errorCount === 4) {
				setTimeout(function() {
					alert(
						"Oops! Seems like your preview isn't updating. It's recommended to switch to the web app: https://webmakerapp.com/app/.\n\n If you still want to get the extension working, please try the following steps until it fixes:\n - Refresh Web Maker\n - Restart browser\n - Update browser\n - Reinstall Web Maker (don't forget to export all your creations from saved items pane (click the OPEN button) before reinstalling)\n\nIf nothing works, please tweet out to @webmakerApp."
					);
					trackEvent('ui', 'writeFileMessageSeen');
				}, 1000);
			}
		};
	}

	// utils.log('writing file ', name);
	window.webkitRequestFileSystem(
		window.TEMPORARY,
		1024 * 1024 * 5,
		function(fs) {
			fs.root.getFile(
				name,
				{
					create: true
				},
				function(fileEntry) {
					fileEntry.createWriter(fileWriter => {
						function onWriteComplete() {
							if (fileWritten) {
								// utils.log('file written ', name);
								return cb();
							}
							fileWritten = true;
							// Set the write pointer to starting of file
							fileWriter.seek(0);
							fileWriter.write(blob);
							return false;
						}
						fileWriter.onwriteend = onWriteComplete;
						// Empty the file contents
						fileWriter.truncate(0);
						// utils.log('truncating file ', name);
					}, getErrorHandler('createWriterFail'));
				},
				getErrorHandler('getFileFail')
			);
		},
		getErrorHandler('webkitRequestFileSystemFail')
	);
}

export function loadJS(src) {
	var d = deferred();
	var ref = window.document.getElementsByTagName('script')[0];
	var script = window.document.createElement('script');
	script.src = src;
	script.async = true;
	ref.parentNode.insertBefore(script, ref);
	script.onload = function() {
		d.resolve();
	};
	return d.promise;
}

/* eslint-disable max-params */
export function getCompleteHtml(html, css, js, item, isForExport) {
	/* eslint-enable max-params */

	if (!item) {
		return '';
	}
	var externalJs = '',
		externalCss = '';
	if (item.externalLibs) {
		externalJs = item.externalLibs.js
			.split('\n')
			.reduce(function(scripts, url) {
				return scripts + (url ? '\n' : '');
			}, '');
		externalCss = item.externalLibs.css
			.split('\n')
			.reduce(function(links, url) {
				return (
					links +
					(url ? '\n<link rel="stylesheet" href="' + url + '"></link>' : '')
				);
			}, '');
	}
	var contents =
		'<!DOCTYPE html>\n' +
		'\n\n' +
		'<meta charset="UTF-8" />\n' +
		externalCss +
		'\n' +
		'\n' +
		'\n' +
		'\n' +
		html +
		'\n' +
		externalJs +
		'\n';

	if (!isForExport) {
		contents +=
			'';
	}

	if (item.jsMode === JsModes.ES6) {
		contents +=
			'';
	}

	if (typeof js === 'string') {
		contents += '\n\n';

	return contents;
}

export function saveAsHtml(item) {
	var htmlPromise = computeHtml(item.html, item.htmlMode);
	var cssPromise = computeCss(item.css, item.cssMode);
	var jsPromise = computeJs(item.js, item.jsMode, false);
	Promise.all([htmlPromise, cssPromise, jsPromise]).then(result => {
		var html = result[0].code,
			css = result[1].code,
			js = result[2].code;

		var fileContent = getCompleteHtml(html, css, js, item, true);

		var d = new Date();
		var fileName = [
			'web-maker',
			d.getFullYear(),
			d.getMonth() + 1,
			d.getDate(),
			d.getHours(),
			d.getMinutes(),
			d.getSeconds()
		].join('-');

		if (item.title) {
			fileName = item.title;
		}
		fileName += '.html';

		var blob = new Blob([fileContent], {
			type: 'text/html;charset=UTF-8'
		});
		downloadFile(fileName, blob);

		trackEvent('fn', 'saveFileComplete');
	});
}

export function handleDownloadsPermission() {
	var d = deferred();
	if (!window.IS_EXTENSION) {
		d.resolve();
		return d.promise;
	}
	chrome.permissions.contains(
		{
			permissions: ['downloads']
		},
		function(result) {
			if (result) {
				d.resolve();
			} else {
				chrome.permissions.request(
					{
						permissions: ['downloads']
					},
					function(granted) {
						if (granted) {
							trackEvent('fn', 'downloadsPermGiven');
							d.resolve();
						} else {
							d.reject();
						}
					}
				);
			}
		}
	);
	return d.promise;
}

/**
 * Return the filename from a passed url.
 * http://a.com/path/file.png  -> file.png
 */
export function getFilenameFromUrl(url) {
	if (!url) {
		return '';
	}
	return url.match(/\/([^/]*)$/)[1];
}

export function prettify(content, type = 'js') {
	const d = deferred();
	const worker = new Worker(
		chrome.extension
			? chrome.extension.getURL('lib/prettier-worker.js')
			: `${BASE_PATH === '/' ? '' : BASE_PATH}/lib/prettier-worker.js`
	);
	worker.postMessage({ content, type });
	worker.addEventListener('message', e => {
		d.resolve(e.data);
		worker.terminate();
	});
	return d.promise;
}

if (window.IS_EXTENSION) {
	document.body.classList.add('is-extension');
} else {
	document.body.classList.add('is-app');
}
<commit_msg>Use strict equality<commit_after>import { trackEvent } from './analytics';

import { computeHtml, computeCss, computeJs } from './computes';
import { JsModes } from './codeModes';
import { deferred } from './deferred';
const esprima = require('esprima');

window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
window.$ = document.querySelector.bind(document);

window.chrome = window.chrome || {};
window.chrome.i18n = {
	getMessage: () => {}
};

window.$all = selector => [...document.querySelectorAll(selector)];
window.IS_EXTENSION = !!window.chrome.extension;
export const BASE_PATH =
	window.chrome.extension ||
	window.DEBUG ||
	process.env.NODE_ENV === 'development'
		? '/'
		: '/app';

var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

/**
 * The following 2 functions are supposed to find the next/previous sibling until the
 * passed `selector` is matched. But for now it actually finds the next/previous
 * element of `this` element in the list of `selector` matched element inside `this`'s
 * parent.
 * @param  Selector that should match for next siblings
 * @return element Next element that mathes `selector`
 */
Node.prototype.nextUntil = function(selector) {
	const siblings = Array.from(this.parentNode.querySelectorAll(selector));
	const index = siblings.indexOf(this);
	return siblings[index + 1];
};

/*
 * @param  Selector that should match for next siblings
 * @return element Next element that mathes `selector`
 */
Node.prototype.previousUntil = function(selector) {
	const siblings = Array.from(this.parentNode.querySelectorAll(selector));
	const index = siblings.indexOf(this);
	return siblings[index - 1];
};

// Safari doesn't have this!
window.requestIdleCallback =
	window.requestIdleCallback ||
	function(fn) {
		setTimeout(fn, 10);
	};

// https://github.com/substack/semver-compare/blob/master/index.js
export function semverCompare(a, b) {
	var pa = a.split('.');
	var pb = b.split('.');
	for (var i = 0; i < 3; i++) {
		var na = Number(pa[i]);
		var nb = Number(pb[i]);
		if (na > nb) {
			return 1;
		}
		if (nb > na) {
			return -1;
		}
		if (!isNaN(na) && isNaN(nb)) {
			return 1;
		}
		if (isNaN(na) && !isNaN(nb)) {
			return -1;
		}
	}
	return 0;
}

export function generateRandomId(len) {
	var length = len || 10;
	var id = '';
	for (var i = length; i--; ) {
		id += alphaNum[~~(Math.random() * alphaNum.length)];
	}
	return id;
}

export function onButtonClick(btn, listener) {
	btn.addEventListener('click', function buttonClickListener(e) {
		listener(e);
		return false;
	});
}

export function log() {
	if (window.DEBUG) {
		console.log(Date.now(), ...arguments);
	}
}

/**
 * Adds timed limit on the loops found in the passed code.
 * Contributed by Ariya Hidayat!
 * @param code {string}	Code to be protected from infinite loops.
 */
export function addInfiniteLoopProtection(code, { timeout }) {
	var loopId = 1;
	var patches = [];
	var varPrefix = '_wmloopvar';
	var varStr = 'var %d = Date.now();\n';
	var checkStr = `\nif (Date.now() - %d > ${timeout}) { window.top.previewException(new Error("Infinite loop")); break;}\n`;

	esprima.parse(
		code,
		{
			tolerant: true,
			range: true,
			jsx: true
		},
		function(node) {
			switch (node.type) {
				case 'DoWhileStatement':
				case 'ForStatement':
				case 'ForInStatement':
				case 'ForOfStatement':
				case 'WhileStatement':
					var start = 1 + node.body.range[0];
					var end = node.body.range[1];
					var prolog = checkStr.replace('%d', varPrefix + loopId);
					var epilog = '';

					if (node.body.type !== 'BlockStatement') {
						// `while(1) doThat()` becomes `while(1) {doThat()}`
						prolog = '{' + prolog;
						epilog = '}';
						--start;
					}

					patches.push({
						pos: start,
						str: prolog
					});
					patches.push({
						pos: end,
						str: epilog
					});
					patches.push({
						pos: node.range[0],
						str: varStr.replace('%d', varPrefix + loopId)
					});
					++loopId;
					break;

				default:
					break;
			}
		}
	);

	/* eslint-disable no-param-reassign */
	patches
		.sort(function(a, b) {
			return b.pos - a.pos;
		})
		.forEach(function(patch) {
			code = code.slice(0, patch.pos) + patch.str + code.slice(patch.pos);
		});

	/* eslint-disable no-param-reassign */
	return code;
}

export function getHumanDate(timestamp) {
	var d = new Date(timestamp);
	var retVal =
		d.getDate() +
		' ' +
		[
			'January',
			'February',
			'March',
			'April',
			'May',
			'June',
			'July',
			'August',
			'September',
			'October',
			'November',
			'December'
		][d.getMonth()] +
		' ' +
		d.getFullYear();
	return retVal;
}

// create a one-time event
export function once(node, type, callback) {
	// create event
	node.addEventListener(type, function(e) {
		// remove event
		e.target.removeEventListener(type, arguments.callee);
		// call handler
		return callback(e);
	});
}

export function downloadFile(fileName, blob) {
	function downloadWithAnchor() {
		var a = document.createElement('a');
		a.href = window.URL.createObjectURL(blob);
		a.download = fileName;
		a.style.display = 'none';
		document.body.appendChild(a);
		a.click();
		a.remove();
	}

	// HACK: because chrome.downloads isn't working on optional permissions
	// anymore.
	downloadWithAnchor();

	/* if (false && window.IS_EXTENSION) {
		chrome.downloads.download({
				url: window.URL.createObjectURL(blob),
				filename: fileName,
				saveAs: true
			},
			() => {
				// If there was an error, just download the file using ANCHOR method.
				if (chrome.runtime.lastError) {
					downloadWithAnchor();
				}
			}
		);
	} else {
		downloadWithAnchor();
	} */
}

export function writeFile(name, blob, cb) {
	var fileWritten = false;

	function getErrorHandler(type) {
		return function() {
			log(arguments);
			trackEvent('fn', 'error', type);
			// When there are too many write errors, show a message.
			writeFile.errorCount = (writeFile.errorCount || 0) + 1;
			if (writeFile.errorCount === 4) {
				setTimeout(function() {
					alert(
						"Oops! Seems like your preview isn't updating. It's recommended to switch to the web app: https://webmakerapp.com/app/.\n\n If you still want to get the extension working, please try the following steps until it fixes:\n - Refresh Web Maker\n - Restart browser\n - Update browser\n - Reinstall Web Maker (don't forget to export all your creations from saved items pane (click the OPEN button) before reinstalling)\n\nIf nothing works, please tweet out to @webmakerApp."
					);
					trackEvent('ui', 'writeFileMessageSeen');
				}, 1000);
			}
		};
	}

	// utils.log('writing file ', name);
	window.webkitRequestFileSystem(
		window.TEMPORARY,
		1024 * 1024 * 5,
		function(fs) {
			fs.root.getFile(
				name,
				{
					create: true
				},
				function(fileEntry) {
					fileEntry.createWriter(fileWriter => {
						function onWriteComplete() {
							if (fileWritten) {
								// utils.log('file written ', name);
								return cb();
							}
							fileWritten = true;
							// Set the write pointer to starting of file
							fileWriter.seek(0);
							fileWriter.write(blob);
							return false;
						}
						fileWriter.onwriteend = onWriteComplete;
						// Empty the file contents
						fileWriter.truncate(0);
						// utils.log('truncating file ', name);
					}, getErrorHandler('createWriterFail'));
				},
				getErrorHandler('getFileFail')
			);
		},
		getErrorHandler('webkitRequestFileSystemFail')
	);
}

export function loadJS(src) {
	var d = deferred();
	var ref = window.document.getElementsByTagName('script')[0];
	var script = window.document.createElement('script');
	script.src = src;
	script.async = true;
	ref.parentNode.insertBefore(script, ref);
	script.onload = function() {
		d.resolve();
	};
	return d.promise;
}

/* eslint-disable max-params */
export function getCompleteHtml(html, css, js, item, isForExport) {
	/* eslint-enable max-params */

	if (!item) {
		return '';
	}
	var externalJs = '',
		externalCss = '';
	if (item.externalLibs) {
		externalJs = item.externalLibs.js
			.split('\n')
			.reduce(function(scripts, url) {
				return scripts + (url ? '\n' : '');
			}, '');
		externalCss = item.externalLibs.css
			.split('\n')
			.reduce(function(links, url) {
				return (
					links +
					(url ? '\n<link rel="stylesheet" href="' + url + '"></link>' : '')
				);
			}, '');
	}
	var contents =
		'<!DOCTYPE html>\n' +
		'\n\n' +
		'<meta charset="UTF-8" />\n' +
		externalCss +
		'\n' +
		'\n' +
		'\n' +
		'\n' +
		html +
		'\n' +
		externalJs +
		'\n';

	if (!isForExport) {
		contents +=
			'';
	}

	if (item.jsMode === JsModes.ES6) {
		contents +=
			'';
	}

	if (typeof js === 'string') {
		contents += '\n\n';

	return contents;
}

export function saveAsHtml(item) {
	var htmlPromise = computeHtml(item.html, item.htmlMode);
	var cssPromise = computeCss(item.css, item.cssMode);
	var jsPromise = computeJs(item.js, item.jsMode, false);
	Promise.all([htmlPromise, cssPromise, jsPromise]).then(result => {
		var html = result[0].code,
			css = result[1].code,
			js = result[2].code;

		var fileContent = getCompleteHtml(html, css, js, item, true);

		var d = new Date();
		var fileName = [
			'web-maker',
			d.getFullYear(),
			d.getMonth() + 1,
			d.getDate(),
			d.getHours(),
			d.getMinutes(),
			d.getSeconds()
		].join('-');

		if (item.title) {
			fileName = item.title;
		}
		fileName += '.html';

		var blob = new Blob([fileContent], {
			type: 'text/html;charset=UTF-8'
		});
		downloadFile(fileName, blob);

		trackEvent('fn', 'saveFileComplete');
	});
}

export function handleDownloadsPermission() {
	var d = deferred();
	if (!window.IS_EXTENSION) {
		d.resolve();
		return d.promise;
	}
	chrome.permissions.contains(
		{
			permissions: ['downloads']
		},
		function(result) {
			if (result) {
				d.resolve();
			} else {
				chrome.permissions.request(
					{
						permissions: ['downloads']
					},
					function(granted) {
						if (granted) {
							trackEvent('fn', 'downloadsPermGiven');
							d.resolve();
						} else {
							d.reject();
						}
					}
				);
			}
		}
	);
	return d.promise;
}

/**
 * Return the filename from a passed url.
 * http://a.com/path/file.png  -> file.png
 */
export function getFilenameFromUrl(url) {
	if (!url) {
		return '';
	}
	return url.match(/\/([^/]*)$/)[1];
}

export function prettify(content, type = 'js') {
	const d = deferred();
	const worker = new Worker(
		chrome.extension
			? chrome.extension.getURL('lib/prettier-worker.js')
			: `${BASE_PATH === '/' ? '' : BASE_PATH}/lib/prettier-worker.js`
	);
	worker.postMessage({ content, type });
	worker.addEventListener('message', e => {
		d.resolve(e.data);
		worker.terminate();
	});
	return d.promise;
}

if (window.IS_EXTENSION) {
	document.body.classList.add('is-extension');
} else {
	document.body.classList.add('is-app');
}
<|endoftext|>


<commit_before>/**
 * @author sabidib http://github.com/sabidib
 */
/**
 * Provides various utility functions for demos.
 */
/*global Flory,window*/

'use strict';
/**
* Function
* Returns a random number (0,1).
* @return {[Float]} a random number (0,1)
*/
Flory.rand = new Flory.RandomGen();
/**
* Provides a Flory.Vector object with the dimension equal
* to the number of defined parameters.
* The returned vector is always has components with ranges [-max , +max]
* @param  {[Float]} max_x
* @param  {[Float]} max_y
* @param  {[Float]} max_z
* @return {[Flory.Vector]}
*/
Flory.getRandomVector = function (max_x, max_y, max_z) {
    var x = Flory.rand.random() * max_x * (0.5 - Flory.rand.random());
    var y = Flory.rand.random() * max_y * (0.5 - Flory.rand.random());
    var z = Flory.rand.random() * max_z * (0.5 - Flory.rand.random());
    if (isNaN(x)) {
        return new Flory.Vector([]);
    } else if (isNaN(y)) {
        return new Flory.Vector([x]);
    } else if (isNaN(z)) {
        return new Flory.Vector([
            x,
            y
        ]);
    } else {
        return new Flory.Vector([
            x,
            y,
            z
        ]);
    }
};
/**
* Given an array of monomers, the function will return
* a Flory.Monomer object in the same dimension as the max dimensions given
* that does not overlap with another monomer based on the radius of the monomers.
* @param  {[Flory.Monomer*]} monomersGiven     [An array of monomer to be checked for overlaps.]
* @param  {[Float]} radius                     [The radius of the new monomer to be created.]
* @param  {[Float]} mass                       [The mass of the monomer]
* @param  {[Float]} charge                     [The charge of the monomer]
* @param  {[Float]} min_distance_apart         [The minimum distance between surface of monomers.]
* @param  {[Float]} max_x_dim                  []
* @param  {[Float]} max_y_dim                  []
* @param  {[Float]} max_z_dim                  []
* @return {[Flory.Monomer]}                    []
*/
Flory.getNonOverlappingMonomer = function (monomersGiven, radius, mass, charge, min_distance_apart, max_x_dim, max_y_dim, max_z_dim) {
    var count = 0;
    var position_overlaps, vec, total_min_distance_apart;
    var j;
    var len = monomersGiven.length;
    while (count < 1000000) {
        position_overlaps = false;
        vec = Flory.getRandomVector(max_x_dim, max_y_dim, max_z_dim);
        for (j = 0; j < len; j += 1) {
            total_min_distance_apart = (radius + monomersGiven[j].radius + min_distance_apart) * (radius + monomersGiven[j].radius + min_distance_apart);
            if (monomersGiven[j].position.distanceToSq(vec) <= total_min_distance_apart) {
                position_overlaps = true;
                break;
            }
        }
        if (!position_overlaps) {
            break;
        }
        //If count goes over 1million there probably is not enough room....
        count += 1;
    }
    if (count > 1000000 - 5) {
        console.log('Flory: can\'t place a monomer that does not overlap with another. Tried 1 million times...');
        return undefined;
    }
    return new Flory.Monomer({
        radius: radius,
        charge: charge,
        mass: mass,
        position: vec
    });
};
Flory.generateGUID = function () {
    function s4() {
        return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
};
Flory.isWebGlAvailable = function () {
    try {
        var canvas = document.createElement('canvas');
        return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
    } catch (e) {
        console.log(e);
        return false;
    }
};
<commit_msg>Added request frame timeout<commit_after>/**
 * @author sabidib http://github.com/sabidib
 */
/**
 * Provides various utility functions for demos.
 */
/*global Flory,window*/

'use strict';
/**
* Function
* Returns a random number (0,1).
* @return {[Float]} a random number (0,1)
*/
Flory.rand = new Flory.RandomGen();
/**
* Provides a Flory.Vector object with the dimension equal
* to the number of defined parameters.
* The returned vector is always has components with ranges [-max , +max]
* @param  {[Float]} max_x
* @param  {[Float]} max_y
* @param  {[Float]} max_z
* @return {[Flory.Vector]}
*/
Flory.getRandomVector = function (max_x, max_y, max_z) {
    var x = Flory.rand.random() * max_x * (0.5 - Flory.rand.random());
    var y = Flory.rand.random() * max_y * (0.5 - Flory.rand.random());
    var z = Flory.rand.random() * max_z * (0.5 - Flory.rand.random());
    if (isNaN(x)) {
        return new Flory.Vector([]);
    } else if (isNaN(y)) {
        return new Flory.Vector([x]);
    } else if (isNaN(z)) {
        return new Flory.Vector([
            x,
            y
        ]);
    } else {
        return new Flory.Vector([
            x,
            y,
            z
        ]);
    }
};
/**
* Given an array of monomers, the function will return
* a Flory.Monomer object in the same dimension as the max dimensions given
* that does not overlap with another monomer based on the radius of the monomers.
* @param  {[Flory.Monomer*]} monomersGiven     [An array of monomer to be checked for overlaps.]
* @param  {[Float]} radius                     [The radius of the new monomer to be created.]
* @param  {[Float]} mass                       [The mass of the monomer]
* @param  {[Float]} charge                     [The charge of the monomer]
* @param  {[Float]} min_distance_apart         [The minimum distance between surface of monomers.]
* @param  {[Float]} max_x_dim                  []
* @param  {[Float]} max_y_dim                  []
* @param  {[Float]} max_z_dim                  []
* @return {[Flory.Monomer]}                    []
*/
Flory.getNonOverlappingMonomer = function (monomersGiven, radius, mass, charge, min_distance_apart, max_x_dim, max_y_dim, max_z_dim) {
    var count = 0;
    var position_overlaps, vec, total_min_distance_apart;
    var j;
    var len = monomersGiven.length;
    while (count < 1000000) {
        position_overlaps = false;
        vec = Flory.getRandomVector(max_x_dim, max_y_dim, max_z_dim);
        for (j = 0; j < len; j += 1) {
            total_min_distance_apart = (radius + monomersGiven[j].radius + min_distance_apart) * (radius + monomersGiven[j].radius + min_distance_apart);
            if (monomersGiven[j].position.distanceToSq(vec) <= total_min_distance_apart) {
                position_overlaps = true;
                break;
            }
        }
        if (!position_overlaps) {
            break;
        }
        //If count goes over 1million there probably is not enough room....
        count += 1;
    }
    if (count > 1000000 - 5) {
        console.log('Flory: can\'t place a monomer that does not overlap with another. Tried 1 million times...');
        return undefined;
    }
    return new Flory.Monomer({
        radius: radius,
        charge: charge,
        mass: mass,
        position: vec
    });
};
Flory.generateGUID = function () {
    function s4() {
        return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
};
Flory.isWebGlAvailable = function () {
    try {
        var canvas = document.createElement('canvas');
        return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
    } catch (e) {
        console.log(e);
        return false;
    }
};

/**
 * Behaves the same as setTimeout except uses requestAnimationFrame() where possible for better performance
 * @param {function} fn The callback function
 * @param {int} delay The delay in milliseconds
 */
Flory.requestTimeout = function(fn, delay) {
    if( !window.requestAnimationFrame       &&
        !window.webkitRequestAnimationFrame &&
        !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support
        !window.oRequestAnimationFrame      &&
        !window.msRequestAnimationFrame)
            return window.setTimeout(fn, delay);

    var start = new Date().getTime(),
        handle = new Object();

    function loop(){
        var current = new Date().getTime(),
            delta = current - start;

        delta >= delay ? fn.call() : handle.value = requestAnimFrame(loop);
    };

    handle.value = requestAnimFrame(loop);
    return handle;
};

<|endoftext|>