Last active
December 12, 2021 22:46
-
-
Save declann/8ddd917912863d75641798a7bb52524e to your computer and use it in GitHub Desktop.
saas model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function webpackUniversalModuleDefinition(root, factory) { | |
if(typeof exports === 'object' && typeof module === 'object') | |
module.exports = factory(); | |
else if(typeof define === 'function' && define.amd) | |
define([], factory); | |
else { | |
var a = factory(); | |
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; | |
} | |
})(this, function() { | |
return /******/ (function(modules) { // webpackBootstrap | |
/******/ // The module cache | |
/******/ var installedModules = {}; | |
/******/ | |
/******/ // The require function | |
/******/ function __webpack_require__(moduleId) { | |
/******/ | |
/******/ // Check if module is in cache | |
/******/ if(installedModules[moduleId]) { | |
/******/ return installedModules[moduleId].exports; | |
/******/ } | |
/******/ // Create a new module (and put it into the cache) | |
/******/ var module = installedModules[moduleId] = { | |
/******/ i: moduleId, | |
/******/ l: false, | |
/******/ exports: {} | |
/******/ }; | |
/******/ | |
/******/ // Execute the module function | |
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | |
/******/ | |
/******/ // Flag the module as loaded | |
/******/ module.l = true; | |
/******/ | |
/******/ // Return the exports of the module | |
/******/ return module.exports; | |
/******/ } | |
/******/ | |
/******/ | |
/******/ // expose the modules object (__webpack_modules__) | |
/******/ __webpack_require__.m = modules; | |
/******/ | |
/******/ // expose the module cache | |
/******/ __webpack_require__.c = installedModules; | |
/******/ | |
/******/ // define getter function for harmony exports | |
/******/ __webpack_require__.d = function(exports, name, getter) { | |
/******/ if(!__webpack_require__.o(exports, name)) { | |
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); | |
/******/ } | |
/******/ }; | |
/******/ | |
/******/ // define __esModule on exports | |
/******/ __webpack_require__.r = function(exports) { | |
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | |
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | |
/******/ } | |
/******/ Object.defineProperty(exports, '__esModule', { value: true }); | |
/******/ }; | |
/******/ | |
/******/ // create a fake namespace object | |
/******/ // mode & 1: value is a module id, require it | |
/******/ // mode & 2: merge all properties of value into the ns | |
/******/ // mode & 4: return value when already ns object | |
/******/ // mode & 8|1: behave like require | |
/******/ __webpack_require__.t = function(value, mode) { | |
/******/ if(mode & 1) value = __webpack_require__(value); | |
/******/ if(mode & 8) return value; | |
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; | |
/******/ var ns = Object.create(null); | |
/******/ __webpack_require__.r(ns); | |
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); | |
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); | |
/******/ return ns; | |
/******/ }; | |
/******/ | |
/******/ // getDefaultExport function for compatibility with non-harmony modules | |
/******/ __webpack_require__.n = function(module) { | |
/******/ var getter = module && module.__esModule ? | |
/******/ function getDefault() { return module['default']; } : | |
/******/ function getModuleExports() { return module; }; | |
/******/ __webpack_require__.d(getter, 'a', getter); | |
/******/ return getter; | |
/******/ }; | |
/******/ | |
/******/ // Object.prototype.hasOwnProperty.call | |
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | |
/******/ | |
/******/ // __webpack_public_path__ | |
/******/ __webpack_require__.p = ""; | |
/******/ | |
/******/ | |
/******/ // Load entry module and return exports | |
/******/ return __webpack_require__(__webpack_require__.s = 1); | |
/******/ }) | |
/************************************************************************/ | |
/******/ ([ | |
/* 0 */ | |
/***/ (function(module, __webpack_exports__, __webpack_require__) { | |
"use strict"; | |
/* unused harmony export subs_growth_pc */ | |
/* unused harmony export subs_churn_pc */ | |
/* unused harmony export subs_0_ */ | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return year; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return CAC; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return subs_new_; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return subs_churned_; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return subs; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return expenses; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return revenue; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return profit; }); | |
/* harmony import */ var _rec_cul_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); | |
const subs_growth_pc = ({ | |
subs_growth_pc_in | |
}) => subs_growth_pc_in; | |
const subs_churn_pc = ({ | |
subs_churn_pc_in | |
}) => subs_churn_pc_in; | |
const subs_0_ = ({ | |
subs_0_in | |
}) => subs_0_in; // subs at start of year 0 | |
const year = ({ | |
year_in | |
}) => year_in; | |
const CAC = ({ | |
CAC_in | |
}) => CAC_in; | |
const subs_new_ = ({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
}) => // its hard to find the year boundary needed here when I add expenses to model, when it worked without. Table and good error reporting is very important | |
year({ | |
year_in | |
}) < 0 ? 0 : subs({ | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
year_in: year({ | |
year_in | |
}) - 1 | |
}) * (subs_growth_pc({ | |
subs_growth_pc_in | |
}) / 100); | |
const subs_churned_ = ({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in | |
}) => (subs({ | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
year_in: year({ | |
year_in | |
}) - 1 | |
}) + Object(_rec_cul_js__WEBPACK_IMPORTED_MODULE_0__["subs_new"])({ | |
year_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
})) * subs_churn_pc({ | |
subs_churn_pc_in | |
}) / 100; // churn assumption also applies to new subs | |
// subs at end = prev subs at end + new subs@yr - churned subs@yr | |
const subs = ({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in | |
}) => { | |
if (year({ | |
year_in | |
}) < 0) return Object(_rec_cul_js__WEBPACK_IMPORTED_MODULE_0__["subs_0"])({ | |
subs_0_in | |
});else return subs({ | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
year_in: year({ | |
year_in | |
}) - 1 | |
}) + Object(_rec_cul_js__WEBPACK_IMPORTED_MODULE_0__["subs_new"])({ | |
year_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
}) - Object(_rec_cul_js__WEBPACK_IMPORTED_MODULE_0__["subs_churned"])({ | |
year_in, | |
subs_churned_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in | |
}); | |
}; // => can project subs given subs_0, growth and churn rates | |
const expenses = ({ | |
year_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in, | |
CAC_in | |
}) => Object(_rec_cul_js__WEBPACK_IMPORTED_MODULE_0__["subs_new"])({ | |
year_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
}) * CAC({ | |
CAC_in | |
}); // error? | |
const revenue = ({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in | |
}) => subs({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in | |
}) * 100; | |
const profit = ({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
CAC_in | |
}) => revenue({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in | |
}) - expenses({ | |
year_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in, | |
CAC_in | |
}); | |
/***/ }), | |
/* 1 */ | |
/***/ (function(module, __webpack_exports__, __webpack_require__) { | |
"use strict"; | |
__webpack_require__.r(__webpack_exports__); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "actuals_table", function() { return actuals_table; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_0", function() { return subs_0; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_new_actual", function() { return subs_new_actual; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_churned_actual", function() { return subs_churned_actual; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_new_actual_to", function() { return subs_new_actual_to; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_churned_actual_to", function() { return subs_churned_actual_to; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_new", function() { return subs_new; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_churned", function() { return subs_churned; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ea_start", function() { return ea_start; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ea_end", function() { return ea_end; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_ea", function() { return subs_ea; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_new_experience", function() { return subs_new_experience; }); | |
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subs_churned_experience", function() { return subs_churned_experience; }); | |
/* harmony import */ var _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); | |
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subs", function() { return _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__["e"]; }); | |
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "year", function() { return _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__["h"]; }); | |
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "revenue", function() { return _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__["d"]; }); | |
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expenses", function() { return _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__["b"]; }); | |
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "profit", function() { return _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__["c"]; }); | |
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "CAC", function() { return _expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__["a"]; }); | |
// necessary | |
const actuals_table = ({ | |
actuals_table_in | |
}) => actuals_table_in; // actuals | |
const subs_0 = ({ | |
subs_0_in | |
}) => subs_0_in; // start at 100 subs (this line now redundant!) | |
const subs_new_actual = ({ | |
actuals_table_in, | |
year_in | |
}) => actuals_table({ | |
actuals_table_in | |
})[Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) + 1].subs_new_actual; | |
const subs_churned_actual = ({ | |
actuals_table_in, | |
year_in | |
}) => actuals_table({ | |
actuals_table_in | |
})[Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) + 1].subs_churned_actual; // year up to which actual data should be used, -1=use only expecteds | |
const subs_new_actual_to = ({ | |
subs_new_actual_to_in | |
}) => subs_new_actual_to_in; | |
const subs_churned_actual_to = ({ | |
subs_churned_actual_to_in | |
}) => subs_churned_actual_to_in; // interleave actuals into projections: this rebases expd using actuals? | |
const subs_new = ({ | |
year_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
}) => { | |
if (Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) <= subs_new_actual_to({ | |
subs_new_actual_to_in | |
})) return subs_new_actual({ | |
actuals_table_in, | |
year_in | |
});else return Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* subs_new_ */ "g"])({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
}); // this is an override which uses itself: but it doesn't compile correctly, check memo-loader version? | |
}; | |
const subs_churned = ({ | |
year_in, | |
subs_churned_actual_to_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in | |
}) => { | |
if (Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) <= subs_churned_actual_to({ | |
subs_churned_actual_to_in | |
})) return subs_churned_actual({ | |
actuals_table_in, | |
year_in | |
});else return Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* subs_churned_ */ "f"])({ | |
year_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in | |
}); | |
}; // move away from experience. | |
// just look at projections | |
// => subs({year:x,actuals:x}) | |
const ea_start = ({ | |
ea_start_in | |
}) => ea_start_in; | |
const ea_end = ({ | |
ea_end_in | |
}) => ea_end_in; | |
const subs_ea = ({ | |
subs_0_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in, | |
ea_end_in, | |
ea_start_in | |
}) => [{ | |
type: 'Expected', | |
function: 'subs', | |
value: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* subs */ "e"])({ | |
subs_0_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in, | |
year_in: ea_end({ | |
ea_end_in | |
}), | |
subs_new_actual_to_in: ea_start({ | |
ea_start_in | |
}), | |
subs_churned_actual_to_in: ea_start({ | |
ea_start_in | |
}) | |
}) | |
}, { | |
type: '-> Actual Sales', | |
// this impact will include expd churn on sales impact, alt. split could use 0 decrements and create a balancing 'confounding' amount | |
function: 'subs', | |
value: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* subs */ "e"])({ | |
subs_0_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in, | |
year_in: ea_end({ | |
ea_end_in | |
}), | |
subs_new_actual_to_in: ea_end({ | |
ea_end_in | |
}), | |
subs_churned_actual_to_in: ea_start({ | |
ea_start_in | |
}) | |
}) | |
}, { | |
type: '-> Actual Churn (=Actual)', | |
function: 'subs', | |
value: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* subs */ "e"])({ | |
subs_0_in, | |
actuals_table_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in, | |
year_in: ea_end({ | |
ea_end_in | |
}), | |
subs_new_actual_to_in: ea_end({ | |
ea_end_in | |
}), | |
subs_churned_actual_to_in: ea_end({ | |
ea_end_in | |
}) | |
}) | |
}]; // todo use an impacts abstraction or move subtraction to VL | |
// reconcile actual to expected, experience=A-E | |
// in year | |
// this should be abstracted using a table for clarity | |
const subs_new_experience = ({ | |
year_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in | |
}) => { | |
// now a fn on year | |
const subs_churned_actual_to_in = Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) - 1; | |
return subs_new({ | |
year_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in, | |
subs_new_actual_to_in: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) | |
}) - subs_new({ | |
year_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_churned_actual_to_in, | |
subs_churn_pc_in, | |
subs_growth_pc_in, | |
subs_new_actual_to_in: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) - 1 | |
}); | |
}; | |
const subs_churned_experience = ({ | |
year_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in | |
}) => { | |
// now a fn on year | |
const subs_new_actual_to_in = Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}); | |
return subs_churned({ | |
year_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in, | |
subs_churned_actual_to_in: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) | |
}) - subs_churned({ | |
year_in, | |
actuals_table_in, | |
subs_0_in, | |
subs_new_actual_to_in, | |
subs_growth_pc_in, | |
subs_churn_pc_in, | |
subs_churned_actual_to_in: Object(_expected_cul_js_cul_scope_id_1_cul_parent_scope_id_0_location_3f95bccec3f403c5faf2856865ba5649__WEBPACK_IMPORTED_MODULE_0__[/* year */ "h"])({ | |
year_in | |
}) - 1 | |
}); // todo project, constrain rec ordering somewhere | |
}; // re introspection: devtools can probably do this? But messy at that stage, so might not be an option | |
// export to excel with hacked formulae (=7+0*E8) for relationships is probably a nice short-term feature until I get the experience outside | |
// hacked formulae can easily be replaced by proper conversions if I convert JS to Excel in fut | |
// maybe this is important for explanation phase, more impt than technical/memo-loader? | |
/***/ }) | |
/******/ ]); | |
}); | |
//# sourceMappingURL=rec.js.map |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"version":3,"sources":["webpack:///../../../webpack/universalModuleDefinition","webpack:///../../../webpack/bootstrap","webpack:///../../../expected.cul.js","webpack:///../../../rec.cul.js"],"names":["subs_growth_pc","subs_growth_pc_in","subs_churn_pc","subs_churn_pc_in","subs_0","subs_0_in","year","year_in","CAC","CAC_in","subs_new","subs","subs_churned","expenses","revenue","profit","actuals_table","actuals_table_in","subs_new_actual","subs_churned_actual","subs_new_actual_to","subs_new_actual_to_in","subs_churned_actual_to","subs_churned_actual_to_in","subs_new_expected","subs_churned_expected","ea_start","ea_start_in","ea_end","ea_end_in","subs_ea","type","function","value","subs_new_experience","subs_churned_experience"],"mappings":"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","file":"rec.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(this, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","export const subs_growth_pc = () => subs_growth_pc_in;\r\nexport const subs_churn_pc = () => subs_churn_pc_in;\r\nexport const subs_0 = () => subs_0_in; // subs at start of year 0\r\nexport const year = () => year_in;\r\nexport const CAC = () => CAC_in;\r\n\r\nexport const subs_new = () =>\r\n // its hard to find the year boundary needed here when I add expenses to model, when it worked without. Table and good error reporting is very important\r\n year() < 0 ? 0 : subs({ year_in: year() - 1 }) * (subs_growth_pc() / 100);\r\n\r\nexport const subs_churned = () =>\r\n ((subs({ year_in: year() - 1 }) + subs_new()) * subs_churn_pc()) / 100; // churn assumption also applies to new subs\r\n\r\n// subs at end = prev subs at end + new subs@yr - churned subs@yr\r\nexport const subs = () => {\r\n if (year() < 0) return subs_0();\r\n else return subs({ year_in: year() - 1 }) + subs_new() - subs_churned();\r\n};\r\n\r\n// => can project subs given subs_0, growth and churn rates\r\n\r\nexport const expenses = () => subs_new() * CAC(); // error?\r\nexport const revenue = () => subs() * 100;\r\nexport const profit = () => revenue() - expenses();\r\n","import {\r\n subs,\r\n subs_new as subs_new_expected,\r\n subs_churned as subs_churned_expected,\r\n year,\r\n revenue,\r\n expenses,\r\n profit,\r\n CAC,\r\n} from './expected.cul.js';\r\nexport { subs, year };\r\nexport { revenue, expenses, profit, CAC }; // necessary\r\n\r\nexport const actuals_table = () => actuals_table_in;\r\n\r\n// actuals\r\nexport const subs_0 = () => subs_0_in; // start at 100 subs (this line now redundant!)\r\nexport const subs_new_actual = () =>\r\n actuals_table()[year() + 1].subs_new_actual;\r\nexport const subs_churned_actual = () =>\r\n actuals_table()[year() + 1].subs_churned_actual;\r\n\r\n// year up to which actual data should be used, -1=use only expecteds\r\nexport const subs_new_actual_to = () => subs_new_actual_to_in;\r\nexport const subs_churned_actual_to = () => subs_churned_actual_to_in;\r\n\r\n// interleave actuals into projections: this rebases expd using actuals?\r\nexport const subs_new = () => {\r\n if (year() <= subs_new_actual_to()) return subs_new_actual();\r\n else return subs_new_expected(); // this is an override which uses itself: but it doesn't compile correctly, check memo-loader version?\r\n};\r\nexport const subs_churned = () => {\r\n if (year() <= subs_churned_actual_to()) return subs_churned_actual();\r\n else return subs_churned_expected();\r\n};\r\n\r\n// move away from experience.\r\n// just look at projections\r\n// => subs({year:x,actuals:x})\r\n\r\nexport const ea_start = () => ea_start_in;\r\nexport const ea_end = () => ea_end_in;\r\n\r\nexport const subs_ea = () => [\r\n {\r\n type: 'Expected',\r\n function: 'subs',\r\n value: subs({\r\n year_in: ea_end(),\r\n subs_new_actual_to_in: ea_start(),\r\n subs_churned_actual_to_in: ea_start(),\r\n }),\r\n },\r\n {\r\n type: '-> Actual Sales', // this impact will include expd churn on sales impact, alt. split could use 0 decrements and create a balancing 'confounding' amount\r\n function: 'subs',\r\n value: subs({\r\n year_in: ea_end(),\r\n subs_new_actual_to_in: ea_end(),\r\n subs_churned_actual_to_in: ea_start(),\r\n }),\r\n },\r\n {\r\n type: '-> Actual Churn (=Actual)',\r\n function: 'subs',\r\n value: subs({\r\n year_in: ea_end(),\r\n subs_new_actual_to_in: ea_end(),\r\n subs_churned_actual_to_in: ea_end(),\r\n }),\r\n },\r\n];\r\n// todo use an impacts abstraction or move subtraction to VL\r\n\r\n// reconcile actual to expected, experience=A-E\r\n// in year\r\n// this should be abstracted using a table for clarity\r\nexport const subs_new_experience = () => {\r\n // now a fn on year\r\n const subs_churned_actual_to_in = year() - 1;\r\n return (\r\n subs_new(/*_actual*/ { subs_new_actual_to_in: year() }) -\r\n subs_new(/*_expected*/ { subs_new_actual_to_in: year() - 1 })\r\n );\r\n};\r\n\r\nexport const subs_churned_experience = () => {\r\n // now a fn on year\r\n const subs_new_actual_to_in = year();\r\n return (\r\n subs_churned(/*_actual*/ { subs_churned_actual_to_in: year() }) -\r\n subs_churned(/*_expected*/ { subs_churned_actual_to_in: year() - 1 })\r\n ); // todo project, constrain rec ordering somewhere\r\n};\r\n\r\n// re introspection: devtools can probably do this? But messy at that stage, so might not be an option\r\n// export to excel with hacked formulae (=7+0*E8) for relationships is probably a nice short-term feature until I get the experience outside\r\n// hacked formulae can easily be replaced by proper conversions if I convert JS to Excel in fut\r\n// maybe this is important for explanation phase, more impt than technical/memo-loader?\r\n"],"sourceRoot":""} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment