code:
# Extended family mode (mod) #

In short, extended family mode replaces the old .relation + .relationTarget system with a completely new system capable of handling a limitless number of relatives. Or at least until your game crashes from trying to handle it all. Fully incompatible with the old system and fully functional with ng+.

## The backbone of the system: .father and .mother ##

Everything about a slave's family can be gathered by looking into her mother and father. Beyond the obvious mother-daughter relation, you can check two separate slaves' parents to see if they are related to each other, allowing for sisters, half-sisters, and with a .birthWeek check, twins with little effort.
The following values are used with .mother and .father:
Valid slave IDs (in other words, a value > 0) - Serves as both a target for checks and as a check itself to see if effort should be expended to search for the parent.
0 - Slave has no known parent. A slave with a parent value of 0 is capable of having a parent added via reRelativeRecruiter
MissingParentIDs (in other words, a value < -2) - Serves as a placeholder to preserve sibling relations in the case of a parent being sold or lost. Outside of extreme cases, this value will never be restored to its previous value. $missingParentID starts at -10000 and decrements after application. On NG+, positive values are incremented the same as a normal slave and checked for validity. Should it be invalid, it will be replaced with $missingParentID. Negative values, on the other hand, are decremented by 1200000. Values of -1 and -2 are ignored by the JS, so don't use them. Also -9999 through -9994 are used by hero slaves to preserve their sibling status no matter when they are purchased or obtained during the same game.

## The limiters: .sisters and .daughters ##
Extended family mode is VERY for loop intensive, and as such, has limiters to prevent it from needlessly looping. A value greater than 0 for either of these slave variables signals that slave has a sibling/daughter for various checks. Furthermore, the value of .sisters and .daughters accurately tracks the number of sisters and daughters, particularly for checks that require all of them to be found. You'll learn to hate these, but on the plus side, they can safely be recalculated with no side effects. Nearly entirely handled by <<AddSlave>> and removeActiveSlave, you do not understand how huge of a plus this is.

## The recruiting check: .canRecruit ##

Checked by reRelativeRecruiter to see if a slave is eligible to have relatives added. Hero slaves, special slaves, and often event slaves are ineligible for recruiting. Gets disabled if the slave is called into the recruiting event but fails to qualify for additional relatives due to unaddable slots or too many existing relatives.

## A quick list of the JS that gets things done and various useful JS calls: ##
```js
sameDad(slave1, slave2) // checks if the slaves share the same father and returns true/false.
sameMom(slave1, slave2) // checks if the slaves share the same mother and returns true/false.
sameTParent(slave1, slave2) // an exception catcher that handles such things as "slave1 knocked up slave2 and got impregnated by slave2, their children will be sisters" and returns the sister variable (0 - not related, 1 - twins, 2 - sisters, 3 - half-sisters). (subJS, never call on its own)
areTwins(slave1, slave2) // checks if the slaves are twins and returns true/false.
areSisters(slave1, slave2) // combines all of the above and returns the sister variable (0 - not related, 1 - twins, 2 - sisters, 3 - half-sisters). A widely used check to identify sister relatives. Generally gated by a .sisters check. Recommended to use in a <<switch>> macro instead of calling it for each outcome.

totalRelatives(slave) // returns how many relatives a slave has as an integer. Useful both as a check and for its value. Recommended to use as a check in instances where you want a relative, but don't care what it is.

mutualChildren(slave1, slave2, slaves) // checks the slave array for children shared by the two slave arguments and returns the number of mutual children as an integer. Currently used solely to encourage two slaves into a relationship if they have kids together.
```
The utility JS, courtesy of FCGudder. This JS should only be called if you know it will find something, use your limiters! These will always return the only relative if only one outcome is possible, so technically they can be used creatively. randomAvailable JS should be followed with random JS as a fallback for circumstances where you must find something, but would prefer it to be sensible if possible.
```js
randomRelatedSlave(slave, filterFunction) // returns a random related slave to the slave passed into it. filterFunction is called in the following JS but not needed if you just want a random relative.
randomRelatedAvailableSlave(slave) // returns a random available related slave.
randomSister(slave) // returns a random sister.
randomAvailableSister(slave) // returns a random available sister.
randomTwinSister(slave) // returns a random twin.
randomAvailableTwinSister(slave) // returns a random available twin.
randomDaughter(slave) // returns a random daughter.
randomAvailableDaughter(slave) // returns a random available daughter.
randomParent(slave) // returns a random parent.
randomAvailableParent(slave) // returns a random available parent.
```

path: devNotes/Extended Family Mode Explained.md


code:
# The pronouns system #
All references to scene actors shall be made via the pronouns object, returned by the `getPronouns()` function. The properties of the returned object contains strings to be used for referring to the actor or his actions. The object presents three property groups. The first one refers to pronouns by their grammatical names ('noun', 'object', 'pronoun', etc.). The rest of the groups provide the same values, but referred using gender-dependent names: he/she, his/her, etc. They are meant to be used in passage texts, and you can choose any group you like, the actual strings will be based on the slave object, which was passed as argument in the `getPronouns()` call.

## Usage examples ##

```js
const s = getPronouns(aSlave);
`Use ${s.his} mouth`
`Fuck ${s.him}`
`${s.He} is ready`
```

```
<<set _p = getPronouns(aSlave)>>
<<= _p.Girl>>s' butts are for loving
```

## Extending the pronouns system. ##

Consider a degradationism-based society where a slave is a thing. To extend the pronouns system, we create a successor of the `App.Utils.Pronouns` class:

```js
App.Utils.ThingPronouns = class extends App.Utils.Pronouns {
	get pronoun() { return "it" }
	get possessivePronoun() { return "its"; }
	get possessive() { return "its"; }
	get object() { return "its"; }
	get objectReflexive() { return "itself"; }
	get noun() { return "thing"; }
};
```
Notice, we override only the basic gender-neutral properties, and the rest of them use these values. Then we modify the `getPronouns()` code:

```js
if (/*degradationist society condition*/) {
	return new App.Utils.ThingPronouns(slave);
}
return new App.Utils.Pronouns(slave);
```

repo_name: Pecanus/fc

license: mit


code:
QuickList is built from the interaction of six parts.

1. The Quick List option enable/disable control.
2. The list context, basically if there are more than one, and the
	context is correct, the toggle, the table will be available.
3. The Slave Summary Passage contains the Quick List toggle button,
	clicking it either shows or hides the quick list table.
4. The Slave Summary Passage contains the actual quick list table, which
	if shown has a button for each slave name in the list, in columns up
	to 5 wide.
5. The Slave Summary Passage contains invisible `<a>` links or any other
	html element nearby or tied to each slave's name. These are
	generated with an html attribute id set to "slave-##" where ## is the
	slave's ID.
6. The JS code to tie a scroll animation from the visible name buttons
	in the quick list table down to the invisible links/elements.

The slave summary passage is called in many strange contexts, and for
this reason, there is some serious complexity in getting consistent
results. As it stands now, the passage sometimes calls itself
recursively (for facilities), but it doesn't do that for the Main
penthouse page.

The list context is duplicated, so that we can quickly loop over the
list context to get the slave names in the list, all without disturbing
the principal list context for the slave data.

If the list context has more than one slave, and is either the first
call for the Main/penthouse list, or the recursive call for any other
facility, And we haven't *already* built a quick list table, then we
proceed to build the quick list table.

We use special attributes on the built button to name the invisible
link to which we'll navigate, the speed that we'll animate our
navigation and an offset.


code:
# Passages that require a go over for adding clothing and accessories. #

## Hair ##

	Definite:
		descriptionWidgetsStyle.tw
		salon.tw
		cosmeticRulesAssistant.tw

	Possible:
		generateXXSlave.tw
		generateXYSlave.tw
		artWidgets.tw
		saLiveWithHG.tw

		(mostly shaved/bald hairstyle checks, probably not worth checking)
		fPat.tw
		remoteSurgery.tw
		surgeryDegradation.tw
		saLongTermEffects.tw
		saAgent.tw
		rulesAutosurgery.tw
		autoSurgerySettings.tw
		ptWorkaround.tw
		newSlaveIntro.tw
		newChildIntro.tw
		RESS.tw

## Clothes ##

	Definite:
		descriptionWidgetsStyle.tw
		descriptionWidgetsFlesh.tw
		descriptionWidgetsPiercing.tw
		boobs.js
		fAbuse.tw
		walkPast.js
		slaveInteract.tw
		wardrobeUse.tw
		slaveSummaryWidgets.js
		rulesAssistantOptions.js
		toyChest.js
		useGuard.js
		birthWidgets.tw
		peConcubineInterview.tw
		PESS.tw
		RESS.tw

	Possible:
		artWidgets.tw
		saClothes.tw
		saChoosesOwnClothes.tw
		eventSelectionJS.js
		saLiveWithHG.tw
		setupVars.tw
		longSlaveDescription.tw

## Shoes ##

	Definite:
		descriptionWidgetsStyle.tw
		descriptionWidgetsFlesh.tw
		slaveInteract.tw
		walkPast.tw
		wardrobeUse.tw
		slaveSummaryWidgets.js
		rulesAssistant.tw

	Possible:
		saLongTermEffects.tw
		saClothes.tw
		saChoosesOwnClothes.tw
		eventSelectionJS.js
		RESS.tw
		REFI.tw
		saServeThePublic.js
		saWhore.js
		saLiveWithHG.tw
		artWidgets.tw
		reStandardPunishment.tw
		setupVars.tw
		fAnus.tw
		seBirthWidgets.tw
		raWidgets.tw

## Collars ##

	Definite:
		descriptionWidgetsStyle.tw
		fLips.tw
		walkPast.js
		slaveInteract.tw
		fKiss.tw
		wardrobeUse.tw
		rulesAssistant.tw
		RESS.tw

	Possible:
		saLongTermEffects.tw
		saClothes.tw
		saDevotion.tw
		raWidgets.tw
		artWidgets.tw
		reStandardPunishment.tw
		saChoosesOwnClothes.tw
		eventSelectionJS.tw
		assayWidgets.tw

--------------------------------------------------------------------------------------
OUTFITS BY TYPE — FOR REFERENCE ONLY

SEXUAL/EROTIC
=============
	Kitty Lingerie
	Slutty Jewelry
	Fallen Nun
	Chattel Habit
	Body Oil
	Pregnant Lingerie
	Nice Lingerie
	Latex Catsuit
	Bodysuit
	Skimpy Loincloth
	BDSM Pony outfit

FESTIVE/ENTERTAINMENT/TRADITIONAL/CULTURAL
=================================
	Kimono
	Qipao nice/slutty
	Biyelgee Costume
	Harem Gauze
	Dirndl
	Klan Robes
	Lederhosen
	Western Clothing
	Toga
	Huipil
	Bunny Outfit
	Succubus Costume
	Ballgown
	Slavegown
	Minidress
	Haltertop Dress
	Clubslut Netting
	Santa Dress
	Hanbok
	Gothic Lolita

EXERCISE/ATHLETICS
==================
	Leotard
	Monokini
	Stretch pants + croptop
	Spats and tank-top
	String Bikini
	Scalemail Bikini
	Cheerleader

CASUAL/DAILY
============
	Shimapan panties
	Hijab and Abaya
	Hijab and Blouse
	Niqab and Abaya
	Burqa
	Burkini
	Conservative Clothing
	Maternity Dress
	Schoolgirl
	Cutoffs + T-shirt
	Apron

PROFESSIONAL/OTHER
==================
	Maid Nice/Maid Slutty
	Suit nice/slutty
	Nurse nice/slutty

MILITARY/LAW ENFORCEMENT
========================
	Mounty
	Schutzstaffel Uniform nice/slutty
	Red Army Uniform
	Battledress
	Military Uniform
	Battlearmor
	Cybersuit
	Police outfit [Not in-game yet]

path: devNotes/clothing hair and accessory passages.md


code:
# JavaScript Exceptions

## Who captures exceptions?
If we don't catch the error manually, there are three different places where the error ends up being displayed to the
user. The exact place depends on the context of the executed code. These error messages show roughly the same information.

1. Captured and printed by us: `App.UI.DOM.formatException()`, hides path & shows version information.
    * Usually code which displays a passage.
2. Captured and printed by SugarCube: custom modification, hides path & shows version information.
    * Usually old twine passages
3. Captured and printed by Browser: Not hiding anything & does not show version information.
    * Usually callbacks

## Manual exception handling

With the movement away from passages as .tw files error handling is getting more important, especially proper cleanup.

A good example is [this issue](https://gitgud.io/pregmodfan/fc-pregmod/-/issues/2654), the end week animation did not stop because `App.EndWeek.slaveAssignmentReport()` failed, which
meant that the endweek animation stop call wasn't executed.

### Finally

Example of the proper way to handle code that cleans up something and should therefore always be executed:

```js
try {
    // setup code

    // other code, may fail
} finally {
    // cleanup code
}
```

Do note that this will still propagate the error up, it will just execute `cleanup code` first. If you want to handle
the error use `catch`

### Catch

If needed a catch clause can be used as well, but it is usually advisable to only catch specific errors and only if you
know they can be thrown and there is no easy way to prevent them.

Example with catch:

```js
try {
    // code that may throw a RangeError
}  catch (ex instanceof RangeError) {
    // error handling code
}
```

### Reference

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch


code:
## Eye Functions

In all functions `side` can be `left`, `right` or `both` unless stated otherwise.

Eye types: `1`: normal; `2`: glass; `3`: cybernetic
`0` is used as return value if there is no eye, but is never stored in the slave object.

Vision: `0`: blind; `1`: nearsighted (or impaired/blurred); `2`: normal

### Read-only functions

* `hasAnyEyes(slave)`:
    True if slave has at least one eye.

* `hasAnyNaturalEyes(slave)`:
    True if slave has at least one eye that is natural.

* `hasAnyProstheticEyes(slave)`:
    True if slave has at least one eye that is prosthetic (cybernetic or glass).

* `hasAnyCyberneticEyes(slave)`:
    True if slave has at least one eye that is cybernetic.

* `hasBothEyes(slave)`:
    True if slave has both eyes.

* `hasBothNaturalEyes(slave)`:
    True if slave has both eyes and they are natural.

* `hasBothProstheticEyes(slave)`:
    True if slave has both eyes and they are prosthetic (cybernetic or glass).

* `hasBothCyberneticEyes(slave)`:
    True if slave has both eyes and they are cybernetic.

* `hasLeftEye(slave)`:
    True if slave has left eye.

* `hasRightEye(slave)`:
    True if slave has right eye.

* `getLeftEyeType(slave)`:
    Returns type of the left eye.

* `getRightEyeType(slave)`:
    Returns type of the right eye.

* `getLeftEyeVision(slave)`:
    Returns vision of the left eye.

* `getRightEyeVision(slave)`:
    Returns vision of the right eye.

* `getBestVision(slave)`:
    Returns highest vision of both eyes.

* `getWorstVision(slave)`:
    Returns lowest vision of both eyes.

* `anyVisionEquals(slave, vision)`:
    True if one eye has the specified vision.

* `getLeftEyeColor(slave)`:
    Returns color of the left eye. If there is no eye `empty` is returned.

* `getRightEyeColor(slave)`:
    Returns color of the right eye. If there is no eye `empty` is returned.

* `getLeftEyePupil(slave)`:
    Returns the shape of pupil of the left eye. If there is no eye `circular` is returned.

* `getRightEyePupil(slave)`:
    Returns the shape of pupil of the right eye. If there is no eye `circular` is returned.

* `hasVisibleHeterochromia(slave)`:
    True if left and right eye colors are different. Does NOT relate to the genetic quirk.

* `getGeneticEyeColor(slave, side)`:
    Gives the genetic color of the specified eye.
    `both` is not allowed as value of `side`.

* `getLenseCount(slave)`:
    Counts the number of eyes that are not the genetic color.

### Description

* `App.Desc.eyesType(slave)`:
    Fits in a sentence like this: She has {return}.

* `App.Desc.eyeTypeToString(type)`:
    Converts an eye type to a string.
    `1` -> `natural`
    `2` -> `glass`
    `3` -> `artificial`

* `App.Desc.eyesColor(slave, adj = "", eye = "eye", eyes = "eyes")`:
    Fits in a sentence like this: She has {return}.
    `adj` is added in between color and eye like this: `brown wet eyes`.

* `App.Desc.eyeColor(slave)`:
    Fits in a sentence like this: She has {return} eyes.
    Prefer App.Desc.eyesColor if possible as it works reliably with only one eye. Example where this is better: {return}-eyed gaze

* `App.Desc.eyesVision(slave)`:
    Fits in a sentence like this: She has {return}.

* `App.Desc.eyesToVision(slave)`:
    Converts an eye vision to a string.
    `0` -> `blind`
    `1` -> `nearsighted`
    `2` -> `normal`

### Modification

* `eyeSurgery(slave, side, action)`:
    Modifies a slaves eyes.
    Allowed values for `action`:
    No Existing eyes required: `normal`, `glass`, `cybernetic`
    Existing eyes required: `remove`, `blind`, `blur`, `fix`

* `setEyeColor(slave, color, side = "both")`:
    Changes the visible eye color.

* `setEyeColorFull(slave, iris, pupil, sclera, side)`:
    Changes all visible parts of the eye.

* `setGeneticEyeColor(slave, color, heterochromia = false)`:
    Changes the genetic eye color. WARNING: If `heterochromia` is `true`, the function will add the genetic quirk, even if the slave did not have it before.

* `resetEyeColor(slave, side)`:
    Sets the eye color to the genetic color. Takes heterochromia and albinism into account.


code:
# Git setup & work cycle

## First time setup

0. [Install Git for terminal](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) or a Git GUI of your
   choice.

1. Create an account on gitgud if you don't have a usable one.
    * (optional) Add an SSH key to your account for easier pushing. This allows you to connect to gitgud through SHH,
      which doesn't require your credentials every time.

2. Fork the main repository through gitgud interface.
   * (optional) Delete all branches other than pregmod-master, so you don't get them locally when fetching.

3. Clone the repo and then change to the new directory
    * Clicking on the dropdown arrow on the far right blue clone button in the gitgud interface on your fork gives you the relevant URLs.
    * Via terminal: `git clone --depth 1 --single-branch <url-to-your-fork> && cd fc-pregmod`

4. Add the main repository as a remote target
    * Via terminal: `git remote add upstream https://gitgud.io/pregmodfan/fc-pregmod.git`

## Typical cycle with Git:

0. Switch to the pregmod-master branch, then check for and merge any upstream updates
 before updating your remote if any updates are present
    * Via terminal: `git checkout -q pregmod-master && git fetch upstream && git merge upstream/pregmod-master && git push -q`

1. Checkout a new branch for your work
    * Via terminal: `git checkout -b <branch-name>`

2. Make desired changes
3. Add them to be committed
    * Via terminal: `git add *`
4. Commit
	* Make the commit message useful (`Fix X`, `Add Y`, etc.)
    * Via terminal: `git commit -m "MESSAGE"`

5. (optional, but recommended) Run sanityCheck before final push to catch any errors you missed.
    * You can ignore errors that already existed
6. Push result into your forked repository
    * Via terminal:
        * Initially: `git push -u origin $(git rev-parse --abbrev-ref HEAD)`
        * Afterwards `git push` will suffice.

7. Create merge request through gitgud interface.
 * Suggestion: Tick "Delete source branch when merge request is accepted."
  to help automatically tidy up your fork.
8. Checkout `pregmod-master` in preparation of next change.
    * Via terminal: `git checkout -q pregmod-master`
9. Once the merge request was accepted, delete your local branch.
    * Via terminal: `git branch -dq <branch-name>`

To get a list of all current branches run `git branch --list` via terminal.


code:
Induced NCS:
		The idea is a genetic change that you can't undo, once done. It is an expensive damaging process, and the
		first time it is run many of the secondary sexual characteristics development will reverse strongly:
		including height, hips width, shoulders width, dick or clit size, labia or scrotum size, and breast size.
		In addition, from then on, every week a small chance of shrinking any of these items. In addition, growth
		features (drugs, hormones, food) work at a disadvantage, while growth-reversal features (drugs, hormones,
		food) work at an advantage. Finally, precocious puberty is generically incremented, such that drugs,
		hormones or treatments that advance puberty are heightened while simultaneously drugs, hormones or
		treatments that work against puberty are lowered, with the exception of hormone blockers, which work as
		advertised.

Slaves generated with `.inducedNCS` set to 0, and added to the backwards compatibility.

Purchased only in the black market.
		Implemented a skeleton 'illegal goods' black market patterning it after the existing FS shopping in the
		black market.

Added description in the Encyclopedia.

Updated Surgery, unlike most surgery, can't be applied to unhealthy slaves `(health > 0)`.

Updated Surgery Degradation.

Updated sa Drugs.

Updated sa Hormones.

Updated sa Long Term Effects.

Added NCS youthening.

NCS youthening, NCS will youthen slave appearances towards 8 years old if older, while younger slaves will
simply, not appear to age at all.
1. every slave visually appearing less than 9 will not be affected.
2. visually 45 yrs and over will always look 1 year younger each week.
3. from 44 down to 9, the slave accumulates NCSyouthening points every week building towards a sliding youthening value which starts at 2 weeks for 44, and evenly progresses towards 10 weeks for slaves 12 and under.

Formula, slaves <= 8 are ignored.

Calculate `_youtheningDifference` the slaves visual age less 8, yielding 0 to say 38 or so, more than that will be dealt with further down the line. Take the `_youthDifference` divide by four and add .25 to evenly break into 0 below 9, and 10 at 45, round to int to get the `_youtheningLevel`. Subtract `_youtheningLevel` from 11 to find out the `_youtheningRequirement`

Every week, slaves that appear older than 8 year old lolis or shotas will have their NCSyouthening incremented. Then this youthening is tested against the `_youtheningRequirement`, if at or better, the NCS youthens the slave, and resets the `NCSyouthening`.

Slaves generated with `.NCSyouthening` set to `0`, and added to the backwards compatibility.


code:
# Creating your event

It would be useful to have the [JS functions Documentation](devNotes/usefulJSFunctionDocumentation.txt) open and in particular the "Core Slave Functions" section.

First decide your events name e.g. MyEvent
```js
App.Events.MyEvent = class MyEvent extends App.Events.BaseEvent {
	// The event only fires if the optional conditions listed in this array are meet however it can be empty.
	eventPrerequisites() {
			// Conditional example
			return [
				() => V.plot === 1
			];

			// empty example
			return [];
	}

	// Each position in the array correlates to conditions that a slave must meet to be selected however it can be empty.
	actorPrerequisites() {
		// Single slave example
		return [
			[
				s => canWalk(s),
				s => s.fetish !== "mindbroken",
				s => s.devotion >= 50,
				s => s.trust <= 20
			]
		];

		// Dual slave
		return [
			[ // here's the first actor, just like above
				s => canWalk(s),
				s => s.fetish !== "mindbroken",
				s => s.devotion >= 50,
				s => s.trust <= 20
			],
			[ // and in this case the second actor must be the first actor's mother
				s => s.ID === getSlave(this.actors[0]).mother
			]
		];

		// Wants one actor, but "any slave will do"
		return [[]];

		// Empty (no actors at all)
		return [];
	}

	execute(node) {
		/** @type {Array<App.Entity.SlaveState>} */
		let [eventSlave] = this.actors.map(a => getSlave(a));
		const {
			He, he, His, his, him, himself
		} = getPronouns(eventSlave);
		const {
			HeU, heU, hisU, himU, himselfU
		} = getNonlocalPronouns(V.seeDicks).appendSuffix('U');

		// show slave Art
		App.Events.drawEventArt(node, eventSlave, "no clothing");

		let t = [];

		t.push(`Event info text goes here`)

		App.Events.addParagraph(node, t);

		// Event branches
		App.Events.addResponses(node, [
			new App.Events.Result(`Text shown to user`, choiceA),
			...
		]);

		function choiceA() {
			t = [];

			t.push(`choice text goes here`);

			// additional code if need

			// effect on slave e.g.
			eventSlave.devotion += 4;
			eventSlave.trust += 4;
			return t;
		}
	}
};
```
# Dealing with lisping

`const {say, title: Master} = getEnunciation(eventSlave);`
Master can just be template literalled into spoken() and it'll convert it itself.

# Adding your event to the pool

Now that your event has been created it needs to be added to the pool of possible events for it's type which for most
 events, as well as for our example, is random individual event.
This pool can be found at src/events/randomEvent.js.
Simply add your event to the array in App.Events.getIndividualEvents.

# Testing

You can go to the "options page" either sideBar -> Options -> "Game Options" or the "O" key by default.
Then go to the Debug & cheating tab and enable CheatMode.
Once you get to "Random Individual Event" select any slave and at the bottom under DEBUG: there should be
 a input box with "Check Prerequisites and Casting" link next to it.
Per the example under it, place your event's full name into it e.g. App.Events.myEvent and then hit said link.
If everything works as intended you should see output

## Examples

# Single slave
[src/events/RESS/devotedFearfulSlave.js](src/events/RESS/devotedFearfulSlave.js) which was converted as apart of https://gitgud.io/pregmodfan/fc-pregmod/-/merge_requests/8843.

# Dual slave
[src/events/reDevotedTwins.js](src/events/reDevotedTwins.js) which was converted as apart of https://gitgud.io/pregmodfan/fc-pregmod/-/merge_requests/9043.


code:
:: art widgets [nobr widget]

/%
Call as <<AssistantArt>>
Displays assistant images. Currently passage-based.
$args[0]: Image size/center.
	3: Large, right. Example: description.
	2: Medium, right. Example: random events.
%/
<<widget "AssistantArt">>

<<if $imageChoice == 0>> /* RENDERED IMAGES BY SHOKUSHU */

<<switch $assistantAppearance>>
<<case "monstergirl">>
	<<set _fileName = "'resources/renders/assistant monstergirl.png' ">>
<<case "shemale">>
	<<set _fileName = "'resources/renders/assistant shemale.png' ">>
<<case "amazon">>
	<<set _fileName = "'resources/renders/assistant amazon.png' ">>
<<case "businesswoman">>
	<<set _fileName = "'resources/renders/assistant businesswoman.png' ">>
<<case "goddess">>
	<<set _fileName = "'resources/renders/assistant goddess.png' ">>
<<case "schoolgirl">>
	<<set _fileName = "'resources/renders/assistant schoolgirl.png' ">>
<<default>>
	<<set _fileName = "'resources/renders/assistant default.png' ">>
<</switch>>
<<if $args[1] == 3>>
	<<print "">>
<<else>>
	<<print "">>
<</if>>

<</if>> /* CLOSES IMAGE CHOICE */

<</widget>>

/%
Call as <<SlaveArt>>
Displays slave images. Currently passage-based.
$args[0]: Slave.
$args[1]: Image size/center.
	3: Large, right. Example: long slave description.
	2: Medium, right. Example: random events.
	1: Small, left. Example: lists.
	0: Tiny, left. Example: facilities
$args[2]: icon UI Display for vector art, 1 for on.
%/
<<widget "SlaveArt">>
/* This is a nasty workaround for Chrome not rendering overlaid SVG images properly */
<<run jQuery(function() { jQuery('.imageRef').imagesLoaded().always(function() { jQuery('.imageRef').fadeTo(1, 0.999); }); })>>
<<if ndef $args[0].customImage>><<set $args[0].customImage = 0>><</if>>
<<if $args[0].customImage != 0>>

<<set _fileFormat = ($args[0].customImageFormat || "png"),
	_fileName = "'resources/" + $args[0].customImage + "." + _fileFormat + "' ",
	_fileTypeStart = (_fileFormat === "webm" ? "video loop autoplay" : "img"),
	_fileTypeEnd = (_fileFormat === "webm" ? "</video>" : "")>>

<<if $args[1] == 3>>
	<<print "<" + _fileTypeStart + " src=" + _fileName + "style='float:right; border:3px hidden'>" + _fileTypeEnd>>
<<elseif $args[1] == 2>>
	<<print "<" + _fileTypeStart + " src=" + _fileName + "style='float:right; border:3px hidden' width='300' height='300'>" + _fileTypeEnd>>
<<elseif $args[1] == 1>>
	<<print "<" + _fileTypeStart + " src=" + _fileName + "style='float:left; border:3px hidden' width='150' height='150'>" + _fileTypeEnd>>
<<else>>
	<<print "<" + _fileTypeStart + " src=" + _fileName + "style='float:left; border:3px hidden' width='120' height='120'>" + _fileTypeEnd>>
<</if>>

<<elseif $imageChoice == 1>> /* VECTOR ART BY NOX */
<<SVGFilters>>

/* 000-250-006 */
/*
 */
/* 000-250-006 */

<<set _folderLoc = "'resources/vector">>

<<if $args[2] == 1>>
	<<print "">>
<</if>>

/% Set skin color %/
<<set _skinFilter = "filter: url(#skin-" + _.kebabCase($args[0].skin) + ");">>
/% Set hair color %/
<<set _hairFilter = "filter: url(#hair-" + _.kebabCase($args[0].hColor) + ");">>
<<set _pubesFilter = "filter: url(#hair-" + _.kebabCase($args[0].pubicHColor) + ");">>
<<set _axillaryFilter = "filter: url(#hair-" + _.kebabCase($args[0].underArmHColor) + ");">>
<<if $args[0].customHairVector>>
	<<set _hairStyle = $args[0].customHairVector>>
<<else>>
	<<set _hairStyle = ["neat", "ponytail", "messy"].includes($args[0].hStyle) ? $args[0].hStyle : "neat">>
<</if>>

<<set _imgSkinLoc = _folderLoc + "/body/white">>

/% Shoulder width and arm or no arm %/
<<if $args[0].amp != 1>>
<<if $args[0].devotion > 50>>
	<<set _leftArmType = "high">>
	<<set _rightArmType = "high">>
<<elseif $args[0].trust >= -20>>
	<<if $args[0].devotion < -20>>
		<<set _leftArmType = "rebel">>
		<<set _rightArmType = "low">>
	<<elseif $args[0].devotion <= 20>>
		<<set _leftArmType = "low">>
		<<set _rightArmType = "low">>
	<<else>>
		<<set _leftArmType = "mid">>
		<<set _rightArmType = "high">>
	<</if>>
<<else>>
	<<set _leftArmType = "mid">>
	<<set _rightArmType = "mid">>
<</if>>
<<if $args[0].fuckdoll == 0 && $args[0].clothes != "restrictive latex" && $args[0].clothes != "a latex catsuit">>
	<<print "">>
	<<print "">>
<<else>>
	<<if $args[0].fuckdoll != 0>>
		<<set _leftArmType = "mid">>
		<<set _rightArmType = "mid">>
	<</if>>
	<<print "">>
	<<print "">>
<</if>>
<</if>>

/% Hair Aft %/
<<if $args[0].hStyle != "shaved" && $args[0].fuckdoll == 0>>
	<<= "">>
<</if>>

/% Butt %/
<<if $args[0].amp != 1>>
<<if $args[0].butt > 6>>
	<<set _buttSize = 3>>
<<elseif $args[0].butt > 4>>
	<<set _buttSize = 2>>
<<elseif $args[0].butt > 2>>
	<<set _buttSize = 1>>
<<else>>
	<<set _buttSize = 0>>
<</if>>
<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
	<<set _buttSize = _buttSize + " latex">>
	<<print "">>
<<else>>
	<<print "">>
<</if>>
<</if>>

/% Leg + 1 size up when chubby or fat%/
<<if $args[0].hips < 0>>
	<<if $args[0].weight <= 95>>/%Chubby%/
		<<set _legSize = "normal">>
	<<else>>
		<<set _legSize = "narrow">>
	<</if>>
<<elseif $args[0].hips == 0>>
	<<if $args[0].weight <= 95>>/%Chubby%/
		<<set _legSize = "wide">>
	<<else>>
		<<set _legSize = "normal">>
	<</if>>
<<elseif $args[0].hips > 0>>
	<<set _legSize = "wide">>
<</if>>
<<if $args[0].amp == 1>>
	<<set _legSize = "stump " + _legSize>>
<</if>>
<<if ($args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit") && $args[0].amp != 1>>
	<<set _legSize = _legSize + " latex">>
	<<print "">>
<<else>>
	<<print "">>
<</if>>

/% Feet %/
<<if $args[0].amp != 1>>
<<if $args[0].shoes == "heels">>
	<<set _shoesType = "heel">>
<<elseif $args[0].shoes == "extreme heels">>
	<<if $args[0].weight <= 95>>/%Chubby%/
		<<set _shoesType = "extreme heel wide">>
	<<else>>
		<<set _shoesType = "extreme heel">>
	<</if>>
<<elseif $args[0].shoes == "boots">>
	<<if $args[0].weight <= 95>>/%Chubby%/
		<<set _shoesType = "boot wide">>
	<<else>>
		<<set _shoesType = "boot">>
	<</if>>
<<elseif $args[0].shoes == "flats">>
	<<set _shoesType = "flat">>
<<else>>
	<<print "">>
<</if>>
<<if $args[0].shoes == "extreme heels" or $args[0].shoes == "boots">>
	<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
		<<set _shoesType = _shoesType + " latex">>
	<</if>>
	<<print "">>
<</if>>
<<if $args[0].shoes == "heels" or $args[0].shoes == "flats">>
	<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
		<<set _shoesType = _shoesType + " latex">>
		<<print "">>
	<<else>>
		<<print "">>
	<</if>>
<</if>>
<</if>>

/% Torso %/
<<if $args[0].waist < -40>>/*Unnatural*/
	<<if $args[0].weight <= 30>>/%Chubby%/
		<<set _torsoSize = "hourglass">>
	<<else>>
		<<set _torsoSize = "unnatural">>
	<</if>>
<<elseif $args[0].waist <= 10>>/%Hour glass%/
	<<if $args[0].weight <= 30>>/%Chubby%/
		<<set _torsoSize = "normal">>
	<<else>>
		<<set _torsoSize = "hourglass">>
	<</if>>
<<else>>/*Normal*/
	<<set _torsoSize = "normal">>
<</if>>
<<print "">>
<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
	<<set _torsoOutfit = " latex">>
<<elseif $args[0].clothes == "uncomfortable straps">>
	<<set _torsoOutfit = " straps">>
<</if>>
<<if _torsoOutfit>>
	<<print "">>
<</if>>

/*Navel Piercing*/
<<if $args[0].navelPiercing >= 1>>
	<<print "">>
<</if>>
<<if $args[0].navelPiercing == 2>>
	<<print "">>
<</if>>

/% Vagina %/
<<if $args[0].vagina >= 0>>
	<<print "">>
	<<if $args[0].clitPiercing == 1>>
		<<print "">>
	<<elseif $args[0].clitPiercing == 2>>
		<<print "">>
	<<elseif $args[0].clitPiercing == 3>>
		<<print "">>
	<</if>>
	<<if $args[0].vaginaPiercing == 1>>
		<<print "">>
	<<elseif $args[0].vaginaPiercing == 2>>
		<<print "">>
	<</if>>
<</if>>

/% Collar %/
<<switch $args[0].collar>>
<<case "bowtie">>
<<case "ancient Egyptian">>
<<case "nice retirement counter" "cruel retirement counter" "leather with cowbell" "pretty jewelry" "heavy gold" "satin choker" "stylish leather" "neck corset" "shock punishment" "tight steel" "uncomfortable leather" "dildo gag">>
	<<print "">>
<</switch>>

/% Head base image %/
<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
	<<print "">>
<<else>>
	<<print "">>
<</if>>

/% Glasses %/
<<if $args[0].eyewear == "corrective glasses" or $args[0].eyewear == "glasses" or $args[0].eyewear == "blurring glasses">>
	<<print "">>
<</if>>

/% Chastity belt or Pubic hair %/
<<if $args[0].dickAccessory == "chastity" || $args[0].dickAccessory == "anal chastity" || $args[0].dickAccessory == "combined chastity" || $args[0].vaginalAccessory == "chastity belt" || $args[0].vaginalAccessory == "anal chastity" || $args[0].vaginalAccessory == "combined chastity">>
	<<if $args[0].dickAccessory == "chastity" || $args[0].dickAccessory == "combined chastity">>
		<<print "">>
	<</if>>
	<<if $args[0].vaginalAccessory == "chastity belt" || $args[0].vaginalAccessory == "combined chastity">>
		<<print "">>
	<</if>>
	<<print "">>
<<else>>
	<<if $args[0].pubicHStyle != "waxed">>
		<<set _pubicHStyle = ($args[0].pubicHStyle == "in a strip" ? "strip" : $args[0].pubicHStyle)>>
		<<= "">>
	<</if>>
<</if>>

/%if pregnant%/
<<if $args[0].preg > 0>>
	<<print "">>
	<<if $args[0].navelPiercing >= 1>>/*Navel Piercing*/
		<<print "">>
	<</if>>
	<<if $args[0].navelPiercing == 2>>
		<<print "">>
	<</if>>
<</if>>

/% Boob %/
<<if $args[0].boobs < 250>>
	<<set _boobSize = 0>>
<<elseif $args[0].boobs < 500>>
	<<set _boobSize = 1>>
<<elseif $args[0].boobs < 800>>
	<<set _boobSize = 2>>
<<elseif $args[0].boobs < 1600>>
	<<set _boobSize = 3>>
<<elseif $args[0].boobs < 3200>>
	<<set _boobSize = 4>>
<<elseif $args[0].boobs < 6400>>
	<<set _boobSize = 5>>
<<elseif $args[0].boobs < 12000>>
	<<set _boobSize = 6>>
<<else>>
	<<set _boobSize = 7>>
<</if>>

/% Scrotum %/
<<if $args[0].scrotum > 0>>
	<<if $args[0].scrotum >= 6>>
		<<set _ballSize = 4>>
	<<elseif $args[0].scrotum >= 4>>
		<<set _ballSize = 3>>
	<<elseif $args[0].scrotum >= 3>>
		<<set _ballSize = 2>>
	<<elseif $args[0].scrotum >= 2>>
		<<set _ballSize = 1>>
	<<else>>
		<<set _ballSize = 0>>
	<</if>>
<</if>>

/% Penis %/
<<if $args[0].dick > 0>>
	<<if $args[0].dick >= 8>>
		<<set _penisSize = 6>>
	<<elseif $args[0].dick >= 7>>
		<<set _penisSize = 5>>
	<<elseif $args[0].dick >= 6>>
		<<set _penisSize = 4>>
	<<elseif $args[0].dick >= 5>>
		<<set _penisSize = 3>>
	<<elseif $args[0].dick >= 4>>
		<<set _penisSize = 2>>
	<<elseif $args[0].dick >= 2>>
		<<set _penisSize = 1>>
	<<else>>
		<<set _penisSize = 0>>
	<</if>>
<</if>>

/% Boob %/
<<set _needBoobs = 1>>
<<if $args[0].dick > 0>>
<<if canAchieveErection($args[0])>>
<<if _boobSize < 6>>
	<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
		/* normal case: outfit hides boobs */
		<<set _boobOutfit = " latex" >>
	<</if>>
	<<if _boobOutfit >>
		<<print "">>
		<<if $args[0].lactation > 0>>
			<<print "">>
		<</if>>
	<<else>>
		<<print "">>
		<<print "">>
	<</if>>
	/* special case: straps are actually dawn over the boobs */
	<<if $args[0].clothes == "uncomfortable straps">>
		<<set _boobOutfit = " straps" >>
		<<print "">>
	<</if>>
	<<set _needBoobs = 0>>
<</if>>
<</if>>
<</if>>
<<if $args[0].vagina > 0>>
	<<if $args[0].dick > 0>>

		<<if $args[0].scrotum > 0>>
			<<print "">>
		<</if>>
		<<if canAchieveErection($args[0])>>
			<<print "">>
		<<else>>
			<<print "">>
			<<if $args[0].dickAccessory == "chastity" || $args[0].dickAccessory == "combined chastity">>
				<<print "">>
			<</if>>
		<</if>>

	<</if>>
<<else>>
	<<if $args[0].dick > 0>>

		<<if $args[0].scrotum > 0>>
			<<print "">>
		<</if>>
		<<if canAchieveErection($args[0])>>
			<<print "">>
		<<else>>
			<<print "">>
			<<if $args[0].dickAccessory == "chastity" || $args[0].dickAccessory == "combined chastity">>
				<<print "">>
			<</if>>
		<</if>>

	<</if>>
<</if>>
<<if _needBoobs>>
	<<if $args[0].fuckdoll != 0 || $args[0].clothes == "restrictive latex" || $args[0].clothes == "a latex catsuit">>
		<<print "">>
		<<if $args[0].lactation > 0>><<print "">><</if>>
	<<else>>
		<<print "">>
		<<print "">>
	<</if>>
	/* special case: straps are actually dawn over the boobs */
	<<if $args[0].clothes == "uncomfortable straps">>
		<<set _boobOutfit = " straps" >>
		<<print "">>
	<</if>>
<</if>>

/% piercings %/
<<if $args[0].nipplesPiercing == 1>>
	<<print "">>
<<elseif $args[0].nipplesPiercing == 2>>
	<<print "">>
<</if>>
<<if $args[0].areolaePiercing == 1>>
	<<print "">>
<</if>>

/% clavicle %/
<<print "">>

/% Hair Foreground %/
<<if $args[0].hStyle != "shaved" && $args[0].fuckdoll == 0>>
	<<= "">>
<</if>>

<<else>> /* RENDERED IMAGES BY SHOKUSHU */

<<if $args[0].vagina > -1>>
	<<if $args[0].dick > 0>>
		<<if $args[0].balls > 0>>
			<<set _fileName = "futanari">>
		<<else>>
			<<set _fileName = "herm">>
		<</if>>
	<<else>>
		<<set _fileName = "female">>
	<</if>>
<<else>>
	<<if $args[0].balls > 0>>
		<<set _fileName = "shemale">>
	<<else>>
		<<set _fileName = "gelding">>
	<</if>>
<</if>>
<<if $args[0].preg > 10>>
	<<set _fileName = "preg " + _fileName>>
<</if>>
<<if $args[0].boobs < 400>>
	<<set _fileName = _fileName + " small">>
<<elseif $args[0].boobs < 800>>
	<<set _fileName = _fileName + " big">>
<<elseif $args[0].boobs < 6000>>
	<<set _fileName = _fileName + " huge">>
<<else>>
	<<set _fileName = _fileName + " hyper">>
<</if>>
<<if $args[0].muscles > 30>>
	<<set _fileName = _fileName + " muscle">>
<<else>>
	<<set _fileName = _fileName + " soft">>
<</if>>
<<if $args[0].fuckdoll > 0>>
	<<set _fileName = _fileName + " rebellious">>
<<elseif $args[0].devotion <= 20>>
	<<if $args[0].trust < -20>>
		<<set _fileName = _fileName + " reluctant">>
	<<else>>
		<<set _fileName = _fileName + " rebellious">>
	<</if>>
<<elseif $args[0].fetish == "mindbroken">>
	<<set _fileName = _fileName + " reluctant">>
<<elseif $args[0].devotion <= 50 || $args[0].fetishKnown != 1 || ($seeMainFetishes == 0 && $args[1] < 2)>>
	<<set _fileName = _fileName + " obedient">>
<<else>>
	<<if $args[0].fetish == "none">>
		<<set _fileName = _fileName + " obedient">>
	<<else>>
		<<set _fileName = _fileName + " " + $args[0].fetish>>
	<</if>>
<</if>>

<<set _fileName = "'resources/renders/" + _fileName + ".png' ">>
<<if $args[1] == 3>>
	<<print "">>
<<elseif $args[1] == 2>>
	<<print "">>
<<elseif $args[1] == 1>>
	<<print "">>
<<else>>
	<<print "">>
<</if>>

<</if>> /* CLOSES IMAGE CHOICE */

<</widget>>

path: devNotes/legacy files/artWidgets-legacy


code:
:: AssayJS [script]

window.slimCount = function(slaves) {
	var slim = 0;
	var ArcologyZero = State.variables.arcologies[0];

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if ((slave.boobs < 500) && (slave.butt < 3)) {
			if ((slave.muscles <= 30) && (ArcologyZero.FSPhysicalIdealist == "unset") && (slave.weight <= 10) && (ArcologyZero.FSHedonisticDecadence == "unset")) {
				slim += 1;
			} else if (ArcologyZero.FSPhysicalIdealist != "unset") {
				if ((ArcologyZero.FSPhysicalIdealistStrongFat == 1) && (slave.weight <= 30)) {
					slim += 1;
				}
			} else if ((ArcologyZero.FSHedonisticDecadence != "unset") && (slave.weight <= 30)) {
				if (ArcologyZero.FSHedonisticDecadenceStrongFat == 1) {
					slim += 1;
				} else if (slave.muscles <= 30) {
					slim += 1;
				}
			}
		}
	}

	return slim;
}

window.stackedCount = function(slaves) {
	var stacked = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if ((slave.butt > 4) && (slave.boobs > 800)) {
			stacked += 1;
		}
	}

	return stacked;
}

window.moddedCount = function(slaves) {
	var modded = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		var modScore = ModScore(slave);
		var tatScore = TatScore(slave);
		var piercingScore = PiercingScore(slave);
		if ((modScore > 15) || (piercingScore > 8) && (tatScore > 5)) {
			modded += 1;
		}
	}
	return modded;
}

window.unmoddedCount = function(slaves) {
	var unmodded = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		var modScore = ModScore(slave);
		var tatScore = TatScore(slave);
		var piercingScore = PiercingScore(slave);
		if ((modScore > 15) || (piercingScore > 8) && (tatScore > 5))
		; else {
			unmodded += 1;
		}
	}

	return unmodded;
}

window.XYCount = function(slaves) {
	var XY = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if (slave.vagina == -1) {
			XY += 1;
		}
	}
	return XY;
}

window.XXCount = function(slaves) {
	var XX = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if (slave.vagina != -1) {
			State.variables.XX += 1;
		}
	}
	return XX;
}

window.youngCount = function(slaves) {
	var young = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if (slave.visualAge < 30) {
			State.variables.young += 1;
		}
	}
	return young;
}

window.oldCount = function(slaves) {
	var old = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if (slave.visualAge >= 30) {
			State.variables.old += 1;
		}
	}
	return old;
}

window.pregYesCount = function(slaves) {
	var pregYes = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if ((slave.bellyPreg >= 5000) || (slave.bellyImplant >= 5000)) {
			pregYes += 1;
		}
	}
	return pregYes;
}

window.pregNoCount = function(slaves) {
	var pregNo = 0;

	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if ((slave.bellyPreg >= 5000) || (slave.bellyImplant >= 5000))
		; else if ((slave.belly < 100) && (slave.weight < 30) && (!setup.fakeBellies.includes(slave.bellyAccessory))) {
			pregNo += 1;
		}
	}
	return pregNo;
}

window.implantedCount = function(slaves) {
	var implanted = 0;
	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if ((slave.boobsImplant == 0) && (slave.buttImplant == 0) && (slave.waist >= -95) && (slave.lipsImplant == 0) && (slave.faceImplant < 30) && (slave.bellyImplant == -1) && (Math.abs(slave.shouldersImplant) < 2) && (Math.abs(slave.hipsImplant) < 2))
		; else {
			implanted += 1;
		}
	}
	return implanted;
}

window.pureCount = function(slaves) {
	var pure = 0;
	for (var i = 0; i < slaves.length; i++) {
		var slave = slaves[i];
		if ((slave.boobsImplant == 0) && (slave.buttImplant == 0) && (slave.waist >= -95) && (slave.lipsImplant == 0) && (slave.faceImplant < 30) && (slave.bellyImplant == -1) && (Math.abs(slave.shouldersImplant) < 2) && (Math.abs(slave.hipsImplant) < 2)) {
			pure += 1;
		}
	}
	return pure;
}

path: devNotes/legacy files/assayJS.txt