spoclip-kit 4.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/libs.cjs +1 -3
- package/dist/libs.cjs.map +1 -1
- package/dist/libs.d.cts +0 -2
- package/dist/libs.d.ts +0 -2
- package/dist/libs.js +1 -3
- package/dist/libs.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -74,9 +74,7 @@ function calculateOriginalDownloadCostWon(durationSeconds, options = {}) {
|
|
|
74
74
|
// src/libs/gym-gold-charge.ts
|
|
75
75
|
var GYM_GOLD_CHARGE_POLICY = {
|
|
76
76
|
minChargeKrw: 1e4,
|
|
77
|
-
chargeUnitKrw: 1e4
|
|
78
|
-
bonusRate: 0.2,
|
|
79
|
-
bonusRateBps: 2e3
|
|
77
|
+
chargeUnitKrw: 1e4
|
|
80
78
|
};
|
|
81
79
|
function isGymGoldChargeKrwAllowed(chargeKrw) {
|
|
82
80
|
return Number.isFinite(chargeKrw) && Number.isInteger(chargeKrw) && chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw && chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/libs/cost.ts","../src/libs/gym-gold-charge.ts","../src/styles/color.ts","../src/styles/typo.ts"],"sourcesContent":["// Main entry point for spoclip-kit\nexport * from './libs';\nexport * from './types';\nexport * from './styles';\n","export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n bonusRate: 0.2,\n bonusRateBps: 2_000,\n} as const;\n\nexport function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean {\n return (\n Number.isFinite(chargeKrw) &&\n Number.isInteger(chargeKrw) &&\n chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw &&\n chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0\n );\n}\n\nexport function assertValidGymGoldChargeKrw(chargeKrw: number): void {\n if (!Number.isFinite(chargeKrw)) {\n throw new RangeError('chargeKrw must be a finite number');\n }\n\n if (!Number.isInteger(chargeKrw)) {\n throw new RangeError('chargeKrw must be an integer');\n }\n\n if (chargeKrw < GYM_GOLD_CHARGE_POLICY.minChargeKrw) {\n throw new RangeError(\n `chargeKrw must be at least ${GYM_GOLD_CHARGE_POLICY.minChargeKrw}`,\n );\n }\n\n if (chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw !== 0) {\n throw new RangeError(\n `chargeKrw must be a multiple of ${GYM_GOLD_CHARGE_POLICY.chargeUnitKrw}`,\n );\n }\n}\n","const color = {\n primary: '#242535',\n primaryB: '#515265',\n primary2: '#9335FB',\n primary2B: '#6323AA',\n secondary: '#FADD32',\n bgColor: '#F3F4F6',\n error: '#EA2E2E',\n\n white: '#FFFFFF',\n black: '#111111',\n gray1: '#424242',\n gray2: '#616161',\n gray3: '#8E8E8E',\n gray4: '#BDBDBD',\n gray5: '#E0E0E0',\n gray6: '#EDEDED',\n\n sub: '#A3A4BD',\n sub3: '#5561E8',\n sub3b: '#F1F7FF',\n sub4: '#1D1A1A',\n\n point: '#FADD32',\n} as const;\n\n/**\n * @deprecated use color instead (작명 실수 ㅠ)\n */\n\nconst colorV2 = color;\n\nexport { colorV2, color };\n","type TypographyKey =\n | 'h1-24b'\n | 'h1-24m'\n | 'h1-24'\n | 'h2-20b'\n | 'h2-20m'\n | 'h2-20'\n | 'h3-18b'\n | 'h3-18m'\n | 'h3-18'\n | 'b1-16b'\n | 'b1-16m'\n | 'b1-16'\n | 'b2-14b'\n | 'b2-14m'\n | 'b2-14'\n | 'b3-12b'\n | 'b3-12m'\n | 'b3-12'\n | 's1-10b'\n | 's1-10m'\n | 's1-10';\n\nconst typo = {\n 'h1-24b': {\n fontSize: 24,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24m': {\n fontSize: 24,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24': {\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'h2-20b': {\n fontSize: 20,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20m': {\n fontSize: 20,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20': {\n fontSize: 20,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18b': {\n fontSize: 18,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18m': {\n fontSize: 18,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18': {\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16b': {\n fontSize: 16,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16m': {\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16': {\n fontSize: 16,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b2-14b': {\n fontSize: 14,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14m': {\n fontSize: 14,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14': {\n fontSize: 14,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b3-12b': {\n fontSize: 12,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12m': {\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12': {\n fontSize: 12,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 's1-10b': {\n fontSize: 10,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10m': {\n fontSize: 10,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10': {\n fontSize: 10,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n} as const;\n\nconst transformLineheight = (key: TypographyKey) => {\n return typo[key].lineHeight * typo[key].fontSize;\n};\n\nconst mobileTypo = {\n 'h1-24b': {\n ...typo['h1-24b'],\n lineHeight: transformLineheight('h1-24b'),\n },\n\n 'h1-24m': {\n ...typo['h1-24m'],\n lineHeight: transformLineheight('h1-24m'),\n },\n\n 'h1-24': {\n ...typo['h1-24'],\n lineHeight: transformLineheight('h1-24'),\n },\n\n 'h2-20b': {\n ...typo['h2-20b'],\n lineHeight: transformLineheight('h2-20b'),\n },\n\n 'h2-20m': {\n ...typo['h2-20m'],\n lineHeight: transformLineheight('h2-20m'),\n },\n\n 'h2-20': {\n ...typo['h2-20'],\n lineHeight: transformLineheight('h2-20'),\n },\n\n 'h3-18b': {\n ...typo['h3-18b'],\n lineHeight: transformLineheight('h3-18b'),\n },\n\n 'h3-18m': {\n ...typo['h3-18m'],\n lineHeight: transformLineheight('h3-18m'),\n },\n\n 'h3-18': {\n ...typo['h3-18'],\n lineHeight: transformLineheight('h3-18'),\n },\n\n 'b1-16b': {\n ...typo['b1-16b'],\n lineHeight: transformLineheight('b1-16b'),\n },\n\n 'b1-16m': {\n ...typo['b1-16m'],\n lineHeight: transformLineheight('b1-16m'),\n },\n\n 'b1-16': {\n ...typo['b1-16'],\n lineHeight: transformLineheight('b1-16'),\n },\n\n 'b2-14b': {\n ...typo['b2-14b'],\n lineHeight: transformLineheight('b2-14b'),\n },\n\n 'b2-14m': {\n ...typo['b2-14m'],\n lineHeight: transformLineheight('b2-14m'),\n },\n\n 'b2-14': {\n ...typo['b2-14'],\n lineHeight: transformLineheight('b2-14'),\n },\n\n 'b3-12b': {\n ...typo['b3-12b'],\n lineHeight: transformLineheight('b3-12b'),\n },\n\n 'b3-12m': {\n ...typo['b3-12m'],\n lineHeight: transformLineheight('b3-12m'),\n },\n\n 'b3-12': {\n ...typo['b3-12'],\n lineHeight: transformLineheight('b3-12'),\n },\n\n 's1-10b': {\n ...typo['s1-10b'],\n lineHeight: transformLineheight('s1-10b'),\n },\n\n 's1-10m': {\n ...typo['s1-10m'],\n lineHeight: transformLineheight('s1-10m'),\n },\n\n 's1-10': {\n ...typo['s1-10'],\n lineHeight: transformLineheight('s1-10'),\n },\n} as const;\n\nexport { typo, mobileTypo };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/libs/cost.ts","../src/libs/gym-gold-charge.ts","../src/styles/color.ts","../src/styles/typo.ts"],"sourcesContent":["// Main entry point for spoclip-kit\nexport * from './libs';\nexport * from './types';\nexport * from './styles';\n","export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n} as const;\n\nexport function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean {\n return (\n Number.isFinite(chargeKrw) &&\n Number.isInteger(chargeKrw) &&\n chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw &&\n chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0\n );\n}\n\nexport function assertValidGymGoldChargeKrw(chargeKrw: number): void {\n if (!Number.isFinite(chargeKrw)) {\n throw new RangeError('chargeKrw must be a finite number');\n }\n\n if (!Number.isInteger(chargeKrw)) {\n throw new RangeError('chargeKrw must be an integer');\n }\n\n if (chargeKrw < GYM_GOLD_CHARGE_POLICY.minChargeKrw) {\n throw new RangeError(\n `chargeKrw must be at least ${GYM_GOLD_CHARGE_POLICY.minChargeKrw}`,\n );\n }\n\n if (chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw !== 0) {\n throw new RangeError(\n `chargeKrw must be a multiple of ${GYM_GOLD_CHARGE_POLICY.chargeUnitKrw}`,\n );\n }\n}\n","const color = {\n primary: '#242535',\n primaryB: '#515265',\n primary2: '#9335FB',\n primary2B: '#6323AA',\n secondary: '#FADD32',\n bgColor: '#F3F4F6',\n error: '#EA2E2E',\n\n white: '#FFFFFF',\n black: '#111111',\n gray1: '#424242',\n gray2: '#616161',\n gray3: '#8E8E8E',\n gray4: '#BDBDBD',\n gray5: '#E0E0E0',\n gray6: '#EDEDED',\n\n sub: '#A3A4BD',\n sub3: '#5561E8',\n sub3b: '#F1F7FF',\n sub4: '#1D1A1A',\n\n point: '#FADD32',\n} as const;\n\n/**\n * @deprecated use color instead (작명 실수 ㅠ)\n */\n\nconst colorV2 = color;\n\nexport { colorV2, color };\n","type TypographyKey =\n | 'h1-24b'\n | 'h1-24m'\n | 'h1-24'\n | 'h2-20b'\n | 'h2-20m'\n | 'h2-20'\n | 'h3-18b'\n | 'h3-18m'\n | 'h3-18'\n | 'b1-16b'\n | 'b1-16m'\n | 'b1-16'\n | 'b2-14b'\n | 'b2-14m'\n | 'b2-14'\n | 'b3-12b'\n | 'b3-12m'\n | 'b3-12'\n | 's1-10b'\n | 's1-10m'\n | 's1-10';\n\nconst typo = {\n 'h1-24b': {\n fontSize: 24,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24m': {\n fontSize: 24,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24': {\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'h2-20b': {\n fontSize: 20,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20m': {\n fontSize: 20,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20': {\n fontSize: 20,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18b': {\n fontSize: 18,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18m': {\n fontSize: 18,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18': {\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16b': {\n fontSize: 16,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16m': {\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16': {\n fontSize: 16,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b2-14b': {\n fontSize: 14,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14m': {\n fontSize: 14,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14': {\n fontSize: 14,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b3-12b': {\n fontSize: 12,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12m': {\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12': {\n fontSize: 12,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 's1-10b': {\n fontSize: 10,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10m': {\n fontSize: 10,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10': {\n fontSize: 10,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n} as const;\n\nconst transformLineheight = (key: TypographyKey) => {\n return typo[key].lineHeight * typo[key].fontSize;\n};\n\nconst mobileTypo = {\n 'h1-24b': {\n ...typo['h1-24b'],\n lineHeight: transformLineheight('h1-24b'),\n },\n\n 'h1-24m': {\n ...typo['h1-24m'],\n lineHeight: transformLineheight('h1-24m'),\n },\n\n 'h1-24': {\n ...typo['h1-24'],\n lineHeight: transformLineheight('h1-24'),\n },\n\n 'h2-20b': {\n ...typo['h2-20b'],\n lineHeight: transformLineheight('h2-20b'),\n },\n\n 'h2-20m': {\n ...typo['h2-20m'],\n lineHeight: transformLineheight('h2-20m'),\n },\n\n 'h2-20': {\n ...typo['h2-20'],\n lineHeight: transformLineheight('h2-20'),\n },\n\n 'h3-18b': {\n ...typo['h3-18b'],\n lineHeight: transformLineheight('h3-18b'),\n },\n\n 'h3-18m': {\n ...typo['h3-18m'],\n lineHeight: transformLineheight('h3-18m'),\n },\n\n 'h3-18': {\n ...typo['h3-18'],\n lineHeight: transformLineheight('h3-18'),\n },\n\n 'b1-16b': {\n ...typo['b1-16b'],\n lineHeight: transformLineheight('b1-16b'),\n },\n\n 'b1-16m': {\n ...typo['b1-16m'],\n lineHeight: transformLineheight('b1-16m'),\n },\n\n 'b1-16': {\n ...typo['b1-16'],\n lineHeight: transformLineheight('b1-16'),\n },\n\n 'b2-14b': {\n ...typo['b2-14b'],\n lineHeight: transformLineheight('b2-14b'),\n },\n\n 'b2-14m': {\n ...typo['b2-14m'],\n lineHeight: transformLineheight('b2-14m'),\n },\n\n 'b2-14': {\n ...typo['b2-14'],\n lineHeight: transformLineheight('b2-14'),\n },\n\n 'b3-12b': {\n ...typo['b3-12b'],\n lineHeight: transformLineheight('b3-12b'),\n },\n\n 'b3-12m': {\n ...typo['b3-12m'],\n lineHeight: transformLineheight('b3-12m'),\n },\n\n 'b3-12': {\n ...typo['b3-12'],\n lineHeight: transformLineheight('b3-12'),\n },\n\n 's1-10b': {\n ...typo['s1-10b'],\n lineHeight: transformLineheight('s1-10b'),\n },\n\n 's1-10m': {\n ...typo['s1-10m'],\n lineHeight: transformLineheight('s1-10m'),\n },\n\n 's1-10': {\n ...typo['s1-10'],\n lineHeight: transformLineheight('s1-10'),\n },\n} as const;\n\nexport { typo, mobileTypo };\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -38,9 +38,7 @@ function calculateOriginalDownloadCostWon(durationSeconds, options = {}) {
|
|
|
38
38
|
// src/libs/gym-gold-charge.ts
|
|
39
39
|
var GYM_GOLD_CHARGE_POLICY = {
|
|
40
40
|
minChargeKrw: 1e4,
|
|
41
|
-
chargeUnitKrw: 1e4
|
|
42
|
-
bonusRate: 0.2,
|
|
43
|
-
bonusRateBps: 2e3
|
|
41
|
+
chargeUnitKrw: 1e4
|
|
44
42
|
};
|
|
45
43
|
function isGymGoldChargeKrwAllowed(chargeKrw) {
|
|
46
44
|
return Number.isFinite(chargeKrw) && Number.isInteger(chargeKrw) && chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw && chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/libs/cost.ts","../src/libs/gym-gold-charge.ts","../src/styles/color.ts","../src/styles/typo.ts"],"sourcesContent":["export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n bonusRate: 0.2,\n bonusRateBps: 2_000,\n} as const;\n\nexport function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean {\n return (\n Number.isFinite(chargeKrw) &&\n Number.isInteger(chargeKrw) &&\n chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw &&\n chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0\n );\n}\n\nexport function assertValidGymGoldChargeKrw(chargeKrw: number): void {\n if (!Number.isFinite(chargeKrw)) {\n throw new RangeError('chargeKrw must be a finite number');\n }\n\n if (!Number.isInteger(chargeKrw)) {\n throw new RangeError('chargeKrw must be an integer');\n }\n\n if (chargeKrw < GYM_GOLD_CHARGE_POLICY.minChargeKrw) {\n throw new RangeError(\n `chargeKrw must be at least ${GYM_GOLD_CHARGE_POLICY.minChargeKrw}`,\n );\n }\n\n if (chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw !== 0) {\n throw new RangeError(\n `chargeKrw must be a multiple of ${GYM_GOLD_CHARGE_POLICY.chargeUnitKrw}`,\n );\n }\n}\n","const color = {\n primary: '#242535',\n primaryB: '#515265',\n primary2: '#9335FB',\n primary2B: '#6323AA',\n secondary: '#FADD32',\n bgColor: '#F3F4F6',\n error: '#EA2E2E',\n\n white: '#FFFFFF',\n black: '#111111',\n gray1: '#424242',\n gray2: '#616161',\n gray3: '#8E8E8E',\n gray4: '#BDBDBD',\n gray5: '#E0E0E0',\n gray6: '#EDEDED',\n\n sub: '#A3A4BD',\n sub3: '#5561E8',\n sub3b: '#F1F7FF',\n sub4: '#1D1A1A',\n\n point: '#FADD32',\n} as const;\n\n/**\n * @deprecated use color instead (작명 실수 ㅠ)\n */\n\nconst colorV2 = color;\n\nexport { colorV2, color };\n","type TypographyKey =\n | 'h1-24b'\n | 'h1-24m'\n | 'h1-24'\n | 'h2-20b'\n | 'h2-20m'\n | 'h2-20'\n | 'h3-18b'\n | 'h3-18m'\n | 'h3-18'\n | 'b1-16b'\n | 'b1-16m'\n | 'b1-16'\n | 'b2-14b'\n | 'b2-14m'\n | 'b2-14'\n | 'b3-12b'\n | 'b3-12m'\n | 'b3-12'\n | 's1-10b'\n | 's1-10m'\n | 's1-10';\n\nconst typo = {\n 'h1-24b': {\n fontSize: 24,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24m': {\n fontSize: 24,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24': {\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'h2-20b': {\n fontSize: 20,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20m': {\n fontSize: 20,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20': {\n fontSize: 20,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18b': {\n fontSize: 18,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18m': {\n fontSize: 18,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18': {\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16b': {\n fontSize: 16,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16m': {\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16': {\n fontSize: 16,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b2-14b': {\n fontSize: 14,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14m': {\n fontSize: 14,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14': {\n fontSize: 14,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b3-12b': {\n fontSize: 12,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12m': {\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12': {\n fontSize: 12,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 's1-10b': {\n fontSize: 10,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10m': {\n fontSize: 10,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10': {\n fontSize: 10,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n} as const;\n\nconst transformLineheight = (key: TypographyKey) => {\n return typo[key].lineHeight * typo[key].fontSize;\n};\n\nconst mobileTypo = {\n 'h1-24b': {\n ...typo['h1-24b'],\n lineHeight: transformLineheight('h1-24b'),\n },\n\n 'h1-24m': {\n ...typo['h1-24m'],\n lineHeight: transformLineheight('h1-24m'),\n },\n\n 'h1-24': {\n ...typo['h1-24'],\n lineHeight: transformLineheight('h1-24'),\n },\n\n 'h2-20b': {\n ...typo['h2-20b'],\n lineHeight: transformLineheight('h2-20b'),\n },\n\n 'h2-20m': {\n ...typo['h2-20m'],\n lineHeight: transformLineheight('h2-20m'),\n },\n\n 'h2-20': {\n ...typo['h2-20'],\n lineHeight: transformLineheight('h2-20'),\n },\n\n 'h3-18b': {\n ...typo['h3-18b'],\n lineHeight: transformLineheight('h3-18b'),\n },\n\n 'h3-18m': {\n ...typo['h3-18m'],\n lineHeight: transformLineheight('h3-18m'),\n },\n\n 'h3-18': {\n ...typo['h3-18'],\n lineHeight: transformLineheight('h3-18'),\n },\n\n 'b1-16b': {\n ...typo['b1-16b'],\n lineHeight: transformLineheight('b1-16b'),\n },\n\n 'b1-16m': {\n ...typo['b1-16m'],\n lineHeight: transformLineheight('b1-16m'),\n },\n\n 'b1-16': {\n ...typo['b1-16'],\n lineHeight: transformLineheight('b1-16'),\n },\n\n 'b2-14b': {\n ...typo['b2-14b'],\n lineHeight: transformLineheight('b2-14b'),\n },\n\n 'b2-14m': {\n ...typo['b2-14m'],\n lineHeight: transformLineheight('b2-14m'),\n },\n\n 'b2-14': {\n ...typo['b2-14'],\n lineHeight: transformLineheight('b2-14'),\n },\n\n 'b3-12b': {\n ...typo['b3-12b'],\n lineHeight: transformLineheight('b3-12b'),\n },\n\n 'b3-12m': {\n ...typo['b3-12m'],\n lineHeight: transformLineheight('b3-12m'),\n },\n\n 'b3-12': {\n ...typo['b3-12'],\n lineHeight: transformLineheight('b3-12'),\n },\n\n 's1-10b': {\n ...typo['s1-10b'],\n lineHeight: transformLineheight('s1-10b'),\n },\n\n 's1-10m': {\n ...typo['s1-10m'],\n lineHeight: transformLineheight('s1-10m'),\n },\n\n 's1-10': {\n ...typo['s1-10'],\n lineHeight: transformLineheight('s1-10'),\n },\n} as const;\n\nexport { typo, mobileTypo };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/libs/cost.ts","../src/libs/gym-gold-charge.ts","../src/styles/color.ts","../src/styles/typo.ts"],"sourcesContent":["export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n} as const;\n\nexport function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean {\n return (\n Number.isFinite(chargeKrw) &&\n Number.isInteger(chargeKrw) &&\n chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw &&\n chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0\n );\n}\n\nexport function assertValidGymGoldChargeKrw(chargeKrw: number): void {\n if (!Number.isFinite(chargeKrw)) {\n throw new RangeError('chargeKrw must be a finite number');\n }\n\n if (!Number.isInteger(chargeKrw)) {\n throw new RangeError('chargeKrw must be an integer');\n }\n\n if (chargeKrw < GYM_GOLD_CHARGE_POLICY.minChargeKrw) {\n throw new RangeError(\n `chargeKrw must be at least ${GYM_GOLD_CHARGE_POLICY.minChargeKrw}`,\n );\n }\n\n if (chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw !== 0) {\n throw new RangeError(\n `chargeKrw must be a multiple of ${GYM_GOLD_CHARGE_POLICY.chargeUnitKrw}`,\n );\n }\n}\n","const color = {\n primary: '#242535',\n primaryB: '#515265',\n primary2: '#9335FB',\n primary2B: '#6323AA',\n secondary: '#FADD32',\n bgColor: '#F3F4F6',\n error: '#EA2E2E',\n\n white: '#FFFFFF',\n black: '#111111',\n gray1: '#424242',\n gray2: '#616161',\n gray3: '#8E8E8E',\n gray4: '#BDBDBD',\n gray5: '#E0E0E0',\n gray6: '#EDEDED',\n\n sub: '#A3A4BD',\n sub3: '#5561E8',\n sub3b: '#F1F7FF',\n sub4: '#1D1A1A',\n\n point: '#FADD32',\n} as const;\n\n/**\n * @deprecated use color instead (작명 실수 ㅠ)\n */\n\nconst colorV2 = color;\n\nexport { colorV2, color };\n","type TypographyKey =\n | 'h1-24b'\n | 'h1-24m'\n | 'h1-24'\n | 'h2-20b'\n | 'h2-20m'\n | 'h2-20'\n | 'h3-18b'\n | 'h3-18m'\n | 'h3-18'\n | 'b1-16b'\n | 'b1-16m'\n | 'b1-16'\n | 'b2-14b'\n | 'b2-14m'\n | 'b2-14'\n | 'b3-12b'\n | 'b3-12m'\n | 'b3-12'\n | 's1-10b'\n | 's1-10m'\n | 's1-10';\n\nconst typo = {\n 'h1-24b': {\n fontSize: 24,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24m': {\n fontSize: 24,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h1-24': {\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'h2-20b': {\n fontSize: 20,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20m': {\n fontSize: 20,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h2-20': {\n fontSize: 20,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18b': {\n fontSize: 18,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18m': {\n fontSize: 18,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'h3-18': {\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16b': {\n fontSize: 16,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16m': {\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b1-16': {\n fontSize: 16,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b2-14b': {\n fontSize: 14,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14m': {\n fontSize: 14,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b2-14': {\n fontSize: 14,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 'b3-12b': {\n fontSize: 12,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12m': {\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 'b3-12': {\n fontSize: 12,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n\n 's1-10b': {\n fontSize: 10,\n fontWeight: 700,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10m': {\n fontSize: 10,\n fontWeight: 500,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n 's1-10': {\n fontSize: 10,\n fontWeight: 400,\n lineHeight: 1.5,\n letterSpacing: 0,\n },\n} as const;\n\nconst transformLineheight = (key: TypographyKey) => {\n return typo[key].lineHeight * typo[key].fontSize;\n};\n\nconst mobileTypo = {\n 'h1-24b': {\n ...typo['h1-24b'],\n lineHeight: transformLineheight('h1-24b'),\n },\n\n 'h1-24m': {\n ...typo['h1-24m'],\n lineHeight: transformLineheight('h1-24m'),\n },\n\n 'h1-24': {\n ...typo['h1-24'],\n lineHeight: transformLineheight('h1-24'),\n },\n\n 'h2-20b': {\n ...typo['h2-20b'],\n lineHeight: transformLineheight('h2-20b'),\n },\n\n 'h2-20m': {\n ...typo['h2-20m'],\n lineHeight: transformLineheight('h2-20m'),\n },\n\n 'h2-20': {\n ...typo['h2-20'],\n lineHeight: transformLineheight('h2-20'),\n },\n\n 'h3-18b': {\n ...typo['h3-18b'],\n lineHeight: transformLineheight('h3-18b'),\n },\n\n 'h3-18m': {\n ...typo['h3-18m'],\n lineHeight: transformLineheight('h3-18m'),\n },\n\n 'h3-18': {\n ...typo['h3-18'],\n lineHeight: transformLineheight('h3-18'),\n },\n\n 'b1-16b': {\n ...typo['b1-16b'],\n lineHeight: transformLineheight('b1-16b'),\n },\n\n 'b1-16m': {\n ...typo['b1-16m'],\n lineHeight: transformLineheight('b1-16m'),\n },\n\n 'b1-16': {\n ...typo['b1-16'],\n lineHeight: transformLineheight('b1-16'),\n },\n\n 'b2-14b': {\n ...typo['b2-14b'],\n lineHeight: transformLineheight('b2-14b'),\n },\n\n 'b2-14m': {\n ...typo['b2-14m'],\n lineHeight: transformLineheight('b2-14m'),\n },\n\n 'b2-14': {\n ...typo['b2-14'],\n lineHeight: transformLineheight('b2-14'),\n },\n\n 'b3-12b': {\n ...typo['b3-12b'],\n lineHeight: transformLineheight('b3-12b'),\n },\n\n 'b3-12m': {\n ...typo['b3-12m'],\n lineHeight: transformLineheight('b3-12m'),\n },\n\n 'b3-12': {\n ...typo['b3-12'],\n lineHeight: transformLineheight('b3-12'),\n },\n\n 's1-10b': {\n ...typo['s1-10b'],\n lineHeight: transformLineheight('s1-10b'),\n },\n\n 's1-10m': {\n ...typo['s1-10m'],\n lineHeight: transformLineheight('s1-10m'),\n },\n\n 's1-10': {\n ...typo['s1-10'],\n lineHeight: transformLineheight('s1-10'),\n },\n} as const;\n\nexport { typo, mobileTypo };\n"],"mappings":";AAAO,IAAM,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3C,aAAa;AAAA;AAAA;AAAA;AAAA,EAIb,cAAc;AAAA;AAAA;AAAA;AAAA,EAId,uBAAuB;AACzB;AAMO,IAAM,uBAAuB;AAM7B,SAAS,0BAA0B,iBAAkC;AAC1E,SACE,OAAO,SAAS,eAAe,KAAK,mBAAmB;AAE3D;AAYO,SAAS,iCACd,iBACA,UAAuC,CAAC,GAChC;AACR,MAAI,CAAC,OAAO,SAAS,eAAe,KAAK,mBAAmB,EAAG,QAAO;AAEtE,QAAM,EAAE,aAAa,WAAW,IAAI;AAGpC,QAAM,uBAAuB,OAAO,SAAS,UAAU,IACnD,KAAK,IAAI,GAAG,KAAK,MAAM,UAAoB,CAAC,IAC5C;AAGJ,QAAM,kBAAkB,KAAK;AAAA,IAC3B;AAAA,IACA,kBAAkB,8BAA8B;AAAA,EAClD;AACA,MAAI,mBAAmB,EAAG,QAAO;AAEjC,QAAM,qBAAqB,8BAA8B,eAAe;AAExE,QAAM,qBAAqB,cACvB,IAAI,8BAA8B,wBAClC;AAKJ,QAAM,kBACJ,kBAAkB,qBAAqB;AACzC,QAAM,eAAe,KAAK,KAAK,OAAO,gBAAgB,QAAQ,CAAC,CAAC,CAAC;AAEjE,SAAO,eAAe;AACxB;;;AC7EO,IAAM,yBAAyB;AAAA,EACpC,cAAc;AAAA,EACd,eAAe;AACjB;AAEO,SAAS,0BAA0B,WAA4B;AACpE,SACE,OAAO,SAAS,SAAS,KACzB,OAAO,UAAU,SAAS,KAC1B,aAAa,uBAAuB,gBACpC,YAAY,uBAAuB,kBAAkB;AAEzD;AAEO,SAAS,4BAA4B,WAAyB;AACnE,MAAI,CAAC,OAAO,SAAS,SAAS,GAAG;AAC/B,UAAM,IAAI,WAAW,mCAAmC;AAAA,EAC1D;AAEA,MAAI,CAAC,OAAO,UAAU,SAAS,GAAG;AAChC,UAAM,IAAI,WAAW,8BAA8B;AAAA,EACrD;AAEA,MAAI,YAAY,uBAAuB,cAAc;AACnD,UAAM,IAAI;AAAA,MACR,8BAA8B,uBAAuB,YAAY;AAAA,IACnE;AAAA,EACF;AAEA,MAAI,YAAY,uBAAuB,kBAAkB,GAAG;AAC1D,UAAM,IAAI;AAAA,MACR,mCAAmC,uBAAuB,aAAa;AAAA,IACzE;AAAA,EACF;AACF;;;AClCA,IAAM,QAAQ;AAAA,EACZ,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AAAA,EAEP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EAEP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EAEN,OAAO;AACT;AAMA,IAAM,UAAU;;;ACPhB,IAAM,OAAO;AAAA,EACX,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EAEA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EAEA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EAEA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EAEA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AACF;AAEA,IAAM,sBAAsB,CAAC,QAAuB;AAClD,SAAO,KAAK,GAAG,EAAE,aAAa,KAAK,GAAG,EAAE;AAC1C;AAEA,IAAM,aAAa;AAAA,EACjB,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,UAAU;AAAA,IACR,GAAG,KAAK,QAAQ;AAAA,IAChB,YAAY,oBAAoB,QAAQ;AAAA,EAC1C;AAAA,EAEA,SAAS;AAAA,IACP,GAAG,KAAK,OAAO;AAAA,IACf,YAAY,oBAAoB,OAAO;AAAA,EACzC;AACF;","names":[]}
|
package/dist/libs.cjs
CHANGED
|
@@ -70,9 +70,7 @@ function calculateOriginalDownloadCostWon(durationSeconds, options = {}) {
|
|
|
70
70
|
// src/libs/gym-gold-charge.ts
|
|
71
71
|
var GYM_GOLD_CHARGE_POLICY = {
|
|
72
72
|
minChargeKrw: 1e4,
|
|
73
|
-
chargeUnitKrw: 1e4
|
|
74
|
-
bonusRate: 0.2,
|
|
75
|
-
bonusRateBps: 2e3
|
|
73
|
+
chargeUnitKrw: 1e4
|
|
76
74
|
};
|
|
77
75
|
function isGymGoldChargeKrwAllowed(chargeKrw) {
|
|
78
76
|
return Number.isFinite(chargeKrw) && Number.isInteger(chargeKrw) && chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw && chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0;
|
package/dist/libs.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/libs/index.ts","../src/libs/cost.ts","../src/libs/gym-gold-charge.ts"],"sourcesContent":["export * from './cost';\nexport * from './gym-gold-charge';\n","export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n
|
|
1
|
+
{"version":3,"sources":["../src/libs/index.ts","../src/libs/cost.ts","../src/libs/gym-gold-charge.ts"],"sourcesContent":["export * from './cost';\nexport * from './gym-gold-charge';\n","export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n} as const;\n\nexport function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean {\n return (\n Number.isFinite(chargeKrw) &&\n Number.isInteger(chargeKrw) &&\n chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw &&\n chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0\n );\n}\n\nexport function assertValidGymGoldChargeKrw(chargeKrw: number): void {\n if (!Number.isFinite(chargeKrw)) {\n throw new RangeError('chargeKrw must be a finite number');\n }\n\n if (!Number.isInteger(chargeKrw)) {\n throw new RangeError('chargeKrw must be an integer');\n }\n\n if (chargeKrw < GYM_GOLD_CHARGE_POLICY.minChargeKrw) {\n throw new RangeError(\n `chargeKrw must be at least ${GYM_GOLD_CHARGE_POLICY.minChargeKrw}`,\n );\n }\n\n if (chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw !== 0) {\n throw new RangeError(\n `chargeKrw must be a multiple of ${GYM_GOLD_CHARGE_POLICY.chargeUnitKrw}`,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3C,aAAa;AAAA;AAAA;AAAA;AAAA,EAIb,cAAc;AAAA;AAAA;AAAA;AAAA,EAId,uBAAuB;AACzB;AAMO,IAAM,uBAAuB;AAM7B,SAAS,0BAA0B,iBAAkC;AAC1E,SACE,OAAO,SAAS,eAAe,KAAK,mBAAmB;AAE3D;AAYO,SAAS,iCACd,iBACA,UAAuC,CAAC,GAChC;AACR,MAAI,CAAC,OAAO,SAAS,eAAe,KAAK,mBAAmB,EAAG,QAAO;AAEtE,QAAM,EAAE,aAAa,WAAW,IAAI;AAGpC,QAAM,uBAAuB,OAAO,SAAS,UAAU,IACnD,KAAK,IAAI,GAAG,KAAK,MAAM,UAAoB,CAAC,IAC5C;AAGJ,QAAM,kBAAkB,KAAK;AAAA,IAC3B;AAAA,IACA,kBAAkB,8BAA8B;AAAA,EAClD;AACA,MAAI,mBAAmB,EAAG,QAAO;AAEjC,QAAM,qBAAqB,8BAA8B,eAAe;AAExE,QAAM,qBAAqB,cACvB,IAAI,8BAA8B,wBAClC;AAKJ,QAAM,kBACJ,kBAAkB,qBAAqB;AACzC,QAAM,eAAe,KAAK,KAAK,OAAO,gBAAgB,QAAQ,CAAC,CAAC,CAAC;AAEjE,SAAO,eAAe;AACxB;;;AC7EO,IAAM,yBAAyB;AAAA,EACpC,cAAc;AAAA,EACd,eAAe;AACjB;AAEO,SAAS,0BAA0B,WAA4B;AACpE,SACE,OAAO,SAAS,SAAS,KACzB,OAAO,UAAU,SAAS,KAC1B,aAAa,uBAAuB,gBACpC,YAAY,uBAAuB,kBAAkB;AAEzD;AAEO,SAAS,4BAA4B,WAAyB;AACnE,MAAI,CAAC,OAAO,SAAS,SAAS,GAAG;AAC/B,UAAM,IAAI,WAAW,mCAAmC;AAAA,EAC1D;AAEA,MAAI,CAAC,OAAO,UAAU,SAAS,GAAG;AAChC,UAAM,IAAI,WAAW,8BAA8B;AAAA,EACrD;AAEA,MAAI,YAAY,uBAAuB,cAAc;AACnD,UAAM,IAAI;AAAA,MACR,8BAA8B,uBAAuB,YAAY;AAAA,IACnE;AAAA,EACF;AAEA,MAAI,YAAY,uBAAuB,kBAAkB,GAAG;AAC1D,UAAM,IAAI;AAAA,MACR,mCAAmC,uBAAuB,aAAa;AAAA,IACzE;AAAA,EACF;AACF;","names":[]}
|
package/dist/libs.d.cts
CHANGED
|
@@ -38,8 +38,6 @@ declare function calculateOriginalDownloadCostWon(durationSeconds: number, optio
|
|
|
38
38
|
declare const GYM_GOLD_CHARGE_POLICY: {
|
|
39
39
|
readonly minChargeKrw: 10000;
|
|
40
40
|
readonly chargeUnitKrw: 10000;
|
|
41
|
-
readonly bonusRate: 0.2;
|
|
42
|
-
readonly bonusRateBps: 2000;
|
|
43
41
|
};
|
|
44
42
|
declare function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean;
|
|
45
43
|
declare function assertValidGymGoldChargeKrw(chargeKrw: number): void;
|
package/dist/libs.d.ts
CHANGED
|
@@ -38,8 +38,6 @@ declare function calculateOriginalDownloadCostWon(durationSeconds: number, optio
|
|
|
38
38
|
declare const GYM_GOLD_CHARGE_POLICY: {
|
|
39
39
|
readonly minChargeKrw: 10000;
|
|
40
40
|
readonly chargeUnitKrw: 10000;
|
|
41
|
-
readonly bonusRate: 0.2;
|
|
42
|
-
readonly bonusRateBps: 2000;
|
|
43
41
|
};
|
|
44
42
|
declare function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean;
|
|
45
43
|
declare function assertValidGymGoldChargeKrw(chargeKrw: number): void;
|
package/dist/libs.js
CHANGED
|
@@ -38,9 +38,7 @@ function calculateOriginalDownloadCostWon(durationSeconds, options = {}) {
|
|
|
38
38
|
// src/libs/gym-gold-charge.ts
|
|
39
39
|
var GYM_GOLD_CHARGE_POLICY = {
|
|
40
40
|
minChargeKrw: 1e4,
|
|
41
|
-
chargeUnitKrw: 1e4
|
|
42
|
-
bonusRate: 0.2,
|
|
43
|
-
bonusRateBps: 2e3
|
|
41
|
+
chargeUnitKrw: 1e4
|
|
44
42
|
};
|
|
45
43
|
function isGymGoldChargeKrwAllowed(chargeKrw) {
|
|
46
44
|
return Number.isFinite(chargeKrw) && Number.isInteger(chargeKrw) && chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw && chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0;
|
package/dist/libs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/libs/cost.ts","../src/libs/gym-gold-charge.ts"],"sourcesContent":["export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n
|
|
1
|
+
{"version":3,"sources":["../src/libs/cost.ts","../src/libs/gym-gold-charge.ts"],"sourcesContent":["export const ORIGINAL_DOWNLOAD_COST_POLICY = {\n /**\n * 무료 다운로드 구간(초). 멤버십 구분 없이 모든 사용자에게 동일하게 적용한다.\n * 다운로드 길이 중 앞 `freeSeconds`초는 과금에서 제외하고,\n * 이를 초과한 구간에만 `krwPerMinute` 요율을 적용한다 (초과분 과금).\n */\n freeSeconds: 30,\n /**\n * 무료 구간 초과분에 적용하는 분당 KRW 요율. 멤버십 구분 없는 단일 요율.\n */\n krwPerMinute: 100,\n /**\n * 전체 영상 다운로드 시 할인율(10%).\n */\n fullVideoDiscountRate: 0.1,\n} as const;\n\n/**\n * 다운로드 가능한 최소 길이(초).\n * 이보다 짧은 구간은 다운로드 요청 자체를 허용하지 않는다 (server·FE 공용 제약).\n */\nexport const MIN_DOWNLOAD_SECONDS = 10;\n\n/**\n * 다운로드 요청 길이가 허용되는지 검사한다.\n * `durationSeconds >= MIN_DOWNLOAD_SECONDS`일 때만 true.\n */\nexport function isDownloadDurationAllowed(durationSeconds: number): boolean {\n return (\n Number.isFinite(durationSeconds) && durationSeconds >= MIN_DOWNLOAD_SECONDS\n );\n}\n\nexport interface OriginalDownloadCostOptions {\n isFullVideo?: boolean;\n /**\n * 동시에 다운로드할 화각(camera angle) 수. 최소 1, 기본 1.\n * 모든 화각은 동일한 길이로 함께 받으므로 단일 화각 비용 × 화각 수로 과금한다.\n * 1 미만이거나 유한하지 않은 값은 1로 보정한다.\n */\n angleCount?: number;\n}\n\nexport function calculateOriginalDownloadCostWon(\n durationSeconds: number,\n options: OriginalDownloadCostOptions = {},\n): number {\n if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) return 0;\n\n const { isFullVideo, angleCount } = options;\n\n // 화각 수는 최소 1로 보정한다. 정수가 아닌 값은 내림 처리.\n const normalizedAngleCount = Number.isFinite(angleCount)\n ? Math.max(1, Math.floor(angleCount as number))\n : 1;\n\n // 앞 freeSeconds 구간은 과금에서 제외하고 초과분만 과금한다.\n const billableSeconds = Math.max(\n 0,\n durationSeconds - ORIGINAL_DOWNLOAD_COST_POLICY.freeSeconds,\n );\n if (billableSeconds <= 0) return 0;\n\n const unitPricePerSecond = ORIGINAL_DOWNLOAD_COST_POLICY.krwPerMinute / 60;\n\n const discountMultiplier = isFullVideo\n ? 1 - ORIGINAL_DOWNLOAD_COST_POLICY.fullVideoDiscountRate\n : 1;\n\n // 부동소수점 drift(예: 30.000000000000004) 때문에 1원 과다 청구되는 것을 막기 위해\n // 원 단위 미만 노이즈를 보정한 뒤 올림한다. 단일 화각 비용을 원 단위로 확정한 뒤\n // 화각 수만큼 곱한다 (각 화각을 개별 다운로드 건으로 과금).\n const rawCostPerAngle =\n billableSeconds * unitPricePerSecond * discountMultiplier;\n const costPerAngle = Math.ceil(Number(rawCostPerAngle.toFixed(6)));\n\n return costPerAngle * normalizedAngleCount;\n}\n","export const GYM_GOLD_CHARGE_POLICY = {\n minChargeKrw: 10_000,\n chargeUnitKrw: 10_000,\n} as const;\n\nexport function isGymGoldChargeKrwAllowed(chargeKrw: number): boolean {\n return (\n Number.isFinite(chargeKrw) &&\n Number.isInteger(chargeKrw) &&\n chargeKrw >= GYM_GOLD_CHARGE_POLICY.minChargeKrw &&\n chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw === 0\n );\n}\n\nexport function assertValidGymGoldChargeKrw(chargeKrw: number): void {\n if (!Number.isFinite(chargeKrw)) {\n throw new RangeError('chargeKrw must be a finite number');\n }\n\n if (!Number.isInteger(chargeKrw)) {\n throw new RangeError('chargeKrw must be an integer');\n }\n\n if (chargeKrw < GYM_GOLD_CHARGE_POLICY.minChargeKrw) {\n throw new RangeError(\n `chargeKrw must be at least ${GYM_GOLD_CHARGE_POLICY.minChargeKrw}`,\n );\n }\n\n if (chargeKrw % GYM_GOLD_CHARGE_POLICY.chargeUnitKrw !== 0) {\n throw new RangeError(\n `chargeKrw must be a multiple of ${GYM_GOLD_CHARGE_POLICY.chargeUnitKrw}`,\n );\n }\n}\n"],"mappings":";AAAO,IAAM,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3C,aAAa;AAAA;AAAA;AAAA;AAAA,EAIb,cAAc;AAAA;AAAA;AAAA;AAAA,EAId,uBAAuB;AACzB;AAMO,IAAM,uBAAuB;AAM7B,SAAS,0BAA0B,iBAAkC;AAC1E,SACE,OAAO,SAAS,eAAe,KAAK,mBAAmB;AAE3D;AAYO,SAAS,iCACd,iBACA,UAAuC,CAAC,GAChC;AACR,MAAI,CAAC,OAAO,SAAS,eAAe,KAAK,mBAAmB,EAAG,QAAO;AAEtE,QAAM,EAAE,aAAa,WAAW,IAAI;AAGpC,QAAM,uBAAuB,OAAO,SAAS,UAAU,IACnD,KAAK,IAAI,GAAG,KAAK,MAAM,UAAoB,CAAC,IAC5C;AAGJ,QAAM,kBAAkB,KAAK;AAAA,IAC3B;AAAA,IACA,kBAAkB,8BAA8B;AAAA,EAClD;AACA,MAAI,mBAAmB,EAAG,QAAO;AAEjC,QAAM,qBAAqB,8BAA8B,eAAe;AAExE,QAAM,qBAAqB,cACvB,IAAI,8BAA8B,wBAClC;AAKJ,QAAM,kBACJ,kBAAkB,qBAAqB;AACzC,QAAM,eAAe,KAAK,KAAK,OAAO,gBAAgB,QAAQ,CAAC,CAAC,CAAC;AAEjE,SAAO,eAAe;AACxB;;;AC7EO,IAAM,yBAAyB;AAAA,EACpC,cAAc;AAAA,EACd,eAAe;AACjB;AAEO,SAAS,0BAA0B,WAA4B;AACpE,SACE,OAAO,SAAS,SAAS,KACzB,OAAO,UAAU,SAAS,KAC1B,aAAa,uBAAuB,gBACpC,YAAY,uBAAuB,kBAAkB;AAEzD;AAEO,SAAS,4BAA4B,WAAyB;AACnE,MAAI,CAAC,OAAO,SAAS,SAAS,GAAG;AAC/B,UAAM,IAAI,WAAW,mCAAmC;AAAA,EAC1D;AAEA,MAAI,CAAC,OAAO,UAAU,SAAS,GAAG;AAChC,UAAM,IAAI,WAAW,8BAA8B;AAAA,EACrD;AAEA,MAAI,YAAY,uBAAuB,cAAc;AACnD,UAAM,IAAI;AAAA,MACR,8BAA8B,uBAAuB,YAAY;AAAA,IACnE;AAAA,EACF;AAEA,MAAI,YAAY,uBAAuB,kBAAkB,GAAG;AAC1D,UAAM,IAAI;AAAA,MACR,mCAAmC,uBAAuB,aAAa;AAAA,IACzE;AAAA,EACF;AACF;","names":[]}
|