diff --git a/src/tools/index.ts b/src/tools/index.ts index f083ca75..73505234 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -9,6 +9,7 @@ import { tool as cypher } from './encryption'; import { tool as bip39 } from './bip39-generator'; import { tool as dateTimeConverter } from './date-time-converter'; import { tool as gitMemo } from './git-memo'; +import { tool as baseConverter } from './integer-base-converter'; export const toolsByCategory: ToolCategory[] = [ { @@ -19,7 +20,7 @@ export const toolsByCategory: ToolCategory[] = [ { name: 'Converter', icon: LockOpen, - components: [dateTimeConverter, romanNumeralConverter], + components: [dateTimeConverter, baseConverter, romanNumeralConverter], }, { name: 'Development', diff --git a/src/tools/integer-base-converter/index.ts b/src/tools/integer-base-converter/index.ts new file mode 100644 index 00000000..cca640a0 --- /dev/null +++ b/src/tools/integer-base-converter/index.ts @@ -0,0 +1,11 @@ +import { ArrowsLeftRight } from '@vicons/tabler'; +import type { ITool } from '../Tool'; + +export const tool: ITool = { + name: 'Integer base converter', + path: '/base-converter', + description: 'Convert numver between different bases (decimal, hexadecimal, binary, octale, base64, ...)', + keywords: ['integer', 'number', 'base', 'convertion', 'decimal', 'hexadecimal', 'binary', 'octale', 'base64'], + component: () => import('./integer-base-converter.vue'), + icon: ArrowsLeftRight, +}; diff --git a/src/tools/integer-base-converter/integer-base-converter.model.test.ts b/src/tools/integer-base-converter/integer-base-converter.model.test.ts new file mode 100644 index 00000000..e9d91f6f --- /dev/null +++ b/src/tools/integer-base-converter/integer-base-converter.model.test.ts @@ -0,0 +1,17 @@ +import { expect, describe, it } from 'vitest'; +import { convertBase } from './integer-base-converter.model'; + +describe('integer-base-converter', () => { + describe('convertBase', () => { + describe('when the input and target bases are between 2 and 64', () => { + it('should convert integer between different bases', () => { + expect(convertBase({ value: '0', fromBase: 2, toBase: 11 })).toEqual('0'); + expect(convertBase({ value: '0', fromBase: 5, toBase: 2 })).toEqual('0'); + expect(convertBase({ value: '0', fromBase: 10, toBase: 16 })).toEqual('0'); + expect(convertBase({ value: '10100101', fromBase: 2, toBase: 16 })).toEqual('a5'); + expect(convertBase({ value: '192654', fromBase: 10, toBase: 8 })).toEqual('570216'); + expect(convertBase({ value: 'zz', fromBase: 64, toBase: 10 })).toEqual('2275'); + }); + }); + }); +}); diff --git a/src/tools/integer-base-converter/integer-base-converter.model.ts b/src/tools/integer-base-converter/integer-base-converter.model.ts new file mode 100644 index 00000000..c3ed66df --- /dev/null +++ b/src/tools/integer-base-converter/integer-base-converter.model.ts @@ -0,0 +1,20 @@ +export function convertBase({ value, fromBase, toBase }: { value: string; fromBase: number; toBase: number }) { + const range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split(''); + const fromRange = range.slice(0, fromBase); + const toRange = range.slice(0, toBase); + let decValue = value + .split('') + .reverse() + .reduce((carry: number, digit: string, index: number) => { + if (!fromRange.includes(digit)) { + throw new Error('Invalid digit `' + digit + '` for base ' + fromBase + '.'); + } + return (carry += fromRange.indexOf(digit) * Math.pow(fromBase, index)); + }, 0); + let newValue = ''; + while (decValue > 0) { + newValue = toRange[decValue % toBase] + newValue; + decValue = (decValue - (decValue % toBase)) / toBase; + } + return newValue || '0'; +} diff --git a/src/tools/integer-base-converter/integer-base-converter.vue b/src/tools/integer-base-converter/integer-base-converter.vue new file mode 100644 index 00000000..5508b42e --- /dev/null +++ b/src/tools/integer-base-converter/integer-base-converter.vue @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file