{"version":3,"file":"screening.esm.min.js","sources":["../lib/utils/numberToString.js","../lib/utils/numberToPosition.js","../lib/utils/stringToNumber.js","../lib/utils/positionToNumber.js","../lib/plate.js","../lib/generateIconNMRFile.js","../lib/generateIconNMRFileFromPlate.js"],"sourcesContent":["/**\n * Convert number like 1 to string like 'A'\n * @param number\n * @returns\n */\nexport function numberToString(number) {\n    let string = '';\n    while (number !== 0) {\n        string = String.fromCodePoint(((number - 1) % 26) + 65) + string;\n        number = Math.floor((number - 1) / 26);\n    }\n    return string;\n}\n//# sourceMappingURL=numberToString.js.map","import { numberToString } from \"./numberToString.js\";\n/**\n * Convert number like 5 to plate position 'A5'\n * @param number\n * @param width\n * @returns\n */\nexport function numberToPosition(number, width) {\n    if (width === undefined) {\n        throw new Error('need to specify width for numberToPosition');\n    }\n    number--;\n    return (numberToString(Math.floor(number / width) + 1) +\n        String((number % width) + 1));\n}\n//# sourceMappingURL=numberToPosition.js.map","/**\n * Convert string like 'A' to number like 1\n * @param string\n * @returns\n */\nexport function stringToNumber(string) {\n    let number = 0;\n    for (let i = 0; i < string.length; i++) {\n        number *= 26;\n        number += Number(string.codePointAt(i)) - 64;\n    }\n    return number;\n}\n//# sourceMappingURL=stringToNumber.js.map","import { stringToNumber } from \"./stringToNumber.js\";\n/**\n * Convert plate position like 'A5' to 5\n * @param position\n * @param width\n * @returns number\n */\nexport function positionToNumber(position, width) {\n    if (width === undefined) {\n        throw new Error('need to specify width for numberToPosition');\n    }\n    position = position.toUpperCase().replaceAll(/[^0-9A-Z]/g, '');\n    const string = position.replace(/[0-9]+/, '');\n    const number = Number(position.replace(/[A-Z]+/, ''));\n    return (stringToNumber(string) - 1) * width + number * 1;\n}\n//# sourceMappingURL=positionToNumber.js.map","import { numberToPosition } from \"./utils/numberToPosition.js\";\nimport { positionToNumber } from \"./utils/positionToNumber.js\";\nexport class Plate {\n    width;\n    height;\n    size;\n    wells = [];\n    constructor(options = {}) {\n        this.width = options.width ?? 12;\n        this.height = options.height ?? (this.width / 3) * 2;\n        this.size = this.width * this.height;\n        this.initialize();\n    }\n    getWells() {\n        return this.wells;\n    }\n    select(range) {\n        if (range) {\n            // reset all\n            for (const well of this.wells) {\n                well.selected = false;\n            }\n            const reg = /(\\d+)(-(\\d+))?,?/g;\n            let m;\n            while ((m = reg.exec(range))) {\n                const from = Number(m[1]);\n                const to = m[3] ? Number(m[3]) : undefined;\n                if (to && from <= to) {\n                    for (let i = from; i <= to; i++) {\n                        const well = this.wells[i - 1];\n                        if (!isEmpty(well.info))\n                            well.selected = true;\n                    }\n                }\n                else {\n                    const well = this.wells[from - 1];\n                    if (!isEmpty(well.info))\n                        well.selected = true;\n                }\n            }\n        }\n        else {\n            // auto-select wells with info\n            for (const well of this.wells) {\n                well.selected = !isEmpty(well.info);\n            }\n        }\n    }\n    getArrayElement(index) {\n        return this.wells[index];\n    }\n    updateColor() {\n        for (const well of this.wells) {\n            if (isEmpty(well.info)) {\n                // empty well = white\n                well.info.color = 'white';\n            }\n            else if (well.selected) {\n                // selected = strong highlight\n                well.info.color = 'rgba(144, 238, 144, 1)';\n            }\n            else {\n                // unselected = faded highlight\n                well.info.color = 'rgba(144, 238, 144, 0.3)';\n            }\n        }\n    }\n    getByPosition(position) {\n        const index = positionToNumber(position, this.width) - 1;\n        return this.wells[index];\n    }\n    getByNumber(number) {\n        return this.wells[number - 1];\n    }\n    initialize() {\n        this.wells = new Array(this.size);\n        for (let row = 0; row < this.height; row++) {\n            for (let column = 0; column < this.width; column++) {\n                const i = row * this.width + column;\n                this.wells[i] = {\n                    number: i + 1,\n                    position: numberToPosition(i + 1, this.width),\n                    info: {},\n                };\n            }\n        }\n    }\n}\n// ----------- Helpers -----------\nfunction isEmpty(object) {\n    return (object &&\n        typeof object === 'object' &&\n        !Array.isArray(object) &&\n        Object.keys(object).length === 0);\n}\n//# sourceMappingURL=plate.js.map","/**\n * Generate iconNMR text file from requests\n * @param requests - array of PlateRequest objects\n * @param options - options for generating the file\n * @returns iconNMR text file\n */\nexport function generateIconNMRFile(requests, options = {}) {\n    const { eol = '\\r\\n', deleteExistingHolder = false, autoSubmit = false, } = options;\n    const textFile = [];\n    for (const request of requests) {\n        let experimentNumberCounter = 1;\n        const { holder } = request;\n        if (deleteExistingHolder) {\n            textFile.push(`USER ${request.user}`, `HOLDER ${holder}`, 'DELETE'); // this is required to delete already existing entries\n        }\n        textFile.push(`USER ${request.user}`, `HOLDER ${holder}`);\n        if (!autoSubmit)\n            textFile.push('NO_SUBMIT');\n        textFile.push(`NAME ${request.name}`, `TITLE ${request.title}`);\n        for (const experiment of request.experiments) {\n            let experimentNumber = experiment.experimentNumber || experimentNumberCounter++;\n            textFile.push(`EXPNO ${experimentNumber++}`, `SOLVENT ${experiment.solvent}`, `EXPERIMENT ${experiment.experiment}`);\n            if (experiment.parameters && experiment.parameters.length > 0) {\n                const parameters = [];\n                for (const parameter of experiment.parameters) {\n                    parameters.push(parameter.label, parameter.value);\n                }\n                textFile.push(`PARAMETERS ${parameters.join(',')}`);\n            }\n        }\n        textFile.push('');\n    }\n    return textFile.join(eol);\n}\n//# sourceMappingURL=generateIconNMRFile.js.map","import { generateIconNMRFile } from \"./generateIconNMRFile.js\";\nimport { positionToNumber } from \"./utils/positionToNumber.js\";\n/**\n * Generate iconNMR text file from requests with plate positions\n * @param requests - array of PlateRequest objects\n * @param options - options for generating the file\n * @returns iconNMR text file\n */\nexport function generateIconNMRFileFromPlate(requests, options = {}) {\n    const { plateNumber = 1 } = options;\n    const holderRequests = [];\n    for (const request of requests) {\n        const { position, holder, experiments, ...rest } = request;\n        const newHolder = holder ?? getHolder(position, plateNumber);\n        let experimentNumber = getExperimentNumber(position);\n        const experimentsWithHolder = [];\n        for (const experiment of experiments) {\n            experimentsWithHolder.push({\n                experimentNumber: experimentNumber++,\n                ...experiment,\n            });\n        }\n        holderRequests.push({\n            holder: newHolder,\n            experiments: experimentsWithHolder,\n            ...rest,\n        });\n    }\n    return generateIconNMRFile(holderRequests, options);\n}\nfunction getHolder(position, plateNumber) {\n    return plateNumber * 100 + positionToNumber(position, 12);\n}\nfunction getExperimentNumber(position) {\n    return positionToNumber(position, 12) * 10;\n}\n//# sourceMappingURL=generateIconNMRFileFromPlate.js.map"],"names":["numberToString","number","string","String","fromCodePoint","Math","floor","numberToPosition","width","undefined","Error","stringToNumber","i","length","Number","codePointAt","positionToNumber","position","toUpperCase","replaceAll","replace","Plate","height","size","wells","constructor","options","this","initialize","getWells","select","range","well","selected","reg","m","exec","from","to","isEmpty","info","getArrayElement","index","updateColor","color","getByPosition","getByNumber","Array","row","column","object","isArray","Object","keys","generateIconNMRFile","requests","eol","deleteExistingHolder","autoSubmit","textFile","request","experimentNumberCounter","holder","push","user","name","title","experiment","experiments","experimentNumber","solvent","parameters","parameter","label","value","join","generateIconNMRFileFromPlate","plateNumber","holderRequests","rest","newHolder","getHolder","getExperimentNumber","experimentsWithHolder"],"mappings":"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"}