Skip to content

Commit

Permalink
Merge pull request #5 from JakeTrevor/Pentameter-Feature
Browse files Browse the repository at this point in the history
Pentameter feature
  • Loading branch information
JakeTrevor authored Jul 15, 2021
2 parents bf9271a + bc2cac3 commit 06c899a
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 75 deletions.
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function App() {

const [settings, setSettings] = useState(PresetOptions);

console.log(settings);
return (
<div className="app">
<Toolbar
Expand Down
4 changes: 2 additions & 2 deletions src/components/ScanModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { ScannedLine } from "./ScannedLine";
import { scanLine, ScanParagraph } from "../scan";
import { PresetOptions } from "../utils";

export let ScanModule = ({ inputDisplayed }) => {
export let ScanModule = ({ inputDisplayed, settings }) => {
let [text, setText] = useState("");
let lines = ScanParagraph(text, PresetOptions);
let lines = ScanParagraph(text, settings);

let other = inputDisplayed === "in" ? "out" : "in";

Expand Down
15 changes: 14 additions & 1 deletion src/components/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,16 @@ function SettingsButton({ settings, setSettings }) {
function toggleOpen() {
setOpen(!open);
}
function toggleFirst() {
setSettings({
...settings,
first: settings.first === "Hexameter" ? "Pentameter" : "Hexameter",
});
}

let meters = ["Hexameter", "Pentameter", "Elegaic"];
return (
<div>
<div className="meterButton">
<p className="toolbarButton" onClick={toggleOpen}>
{settings.meter}
</p>
Expand All @@ -52,6 +59,7 @@ function SettingsButton({ settings, setSettings }) {
{meters.map((each) => {
return (
<p
key={each}
className="toolbarButton"
onClick={() => {
setSettings({
Expand All @@ -68,6 +76,11 @@ function SettingsButton({ settings, setSettings }) {
</ul>
</div>
)}
{settings.meter === "Elegaic" && (
<button className="toolbarButton" onClick={toggleFirst}>
{settings.first} 1st
</button>
)}
</div>
);
}
7 changes: 6 additions & 1 deletion src/index.sass
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ ul
.toolbarButton:active
background-color: #1a1a1a

.meterButton
display: flex
flex-direction: row

.meterOptions
position: absolute
max-width: 25%
Expand Down Expand Up @@ -158,10 +162,11 @@ ul
.line
font-size: var(--fontSize)
min-height: 2em
padding: 0 10px
padding: 10px
margin: 0
display: flex
flex-direction: column
border-bottom: black solid 1px


.lineSelection
Expand Down
241 changes: 172 additions & 69 deletions src/scan.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//scan.ts
import type {
metaLine,
meter,
quantity,
scannedLineType,
setting,
Expand All @@ -27,13 +28,27 @@ import expressions, {
export let ScanParagraph = (text: string, settings: setting) => {
let lines = text.split("\n");
let done: scannedLineType[] = [];
for (let line of lines) {
done.push(scanLine(line, settings));

if (settings.meter === "Elegaic") {
let currentMeter = settings.first;
for (let line of lines) {
if (line !== "") {
done.push(scanLine(line, currentMeter));
currentMeter =
currentMeter === "Hexameter" ? "Pentameter" : "Hexameter";
}
}
} else {
for (let line of lines) {
if (line !== "") {
done.push(scanLine(line, settings.meter));
}
}
}
return done;
};

export let scanLine = (line: string, settings: setting): scannedLineType => {
export let scanLine = (line: string, meter: meter): scannedLineType => {
let output: scannedLineType = { line: line, raws: [], full: [] }; //initialize output object

let meta: metaLine = undress(line);
Expand All @@ -44,10 +59,10 @@ export let scanLine = (line: string, settings: setting): scannedLineType => {
}
output.raws = dressedRaws;

// now we would switch on settings.meter
// now we would switch on the meter
let toDress: sylMap[][] = [];
switch (settings.meter) {
case "hexameter":
switch (meter) {
case "Hexameter":
for (let each of raws) {
let quantityScans = hexScan(each);
let pos = Object.keys(each).map((elt) => {
Expand All @@ -58,6 +73,19 @@ export let scanLine = (line: string, settings: setting): scannedLineType => {
});
toDress.push(scans);
}
break;
case "Pentameter":
for (let each of raws) {
let quantityScans = penScan(each);
let pos = Object.keys(each).map((elt) => {
return parseInt(elt);
});
let scans = quantityScans.map((elt) => {
return marryUp(elt, pos);
});
toDress.push(scans);
}
break;
}

let done: string[][] = toDress.map((rawGroup) => {
Expand Down Expand Up @@ -215,6 +243,95 @@ export let postScan = (meta: metaLine, markings: sylMap): string => {
return line.join("");
};

/** function that takes a list of permutator outputs (4 binary arrays) and returns a list of complete quantity descriptions; 1 for each arr in the input.
*
* @param { number[][] } arr
* @returns { quantity[][] }
*/
export function arrToQuantity(arr: number[][], meter: meter): quantity[][] {
let output: quantity[][] = [];
for (let each of arr) {
let temp = each.map((el) => {
//first we map each 0 or 1 to an array of quantities.
return el === 0 //if the element is 0, then the foot is long
? (["long", "long", "break"] as quantity[]) //so insert the long foot template
: (["long", "short", "short", "break"] as quantity[]); //else, insert the short foot template
});

//we have now an array of quantity arrays; (quantity[][])
switch (meter) {
case "Hexameter":
temp.push([
"long",
"short",
"short",
"break",
"long",
"undefined",
] as quantity[]);
break;
case "Pentameter":
temp.push([
"long",
"break",
"long",
"short",
"short",
"break",
"long",
"short",
"short",
"break",
"long",
]);
break;
}

//we then flatten this by concatenating all the inner lists
//resulting in a quant[]
let temp2 = temp.reduce((acc, val) => {
return acc.concat(val);
});

output.push(temp2); //push this to the list of meters
}
return output;
}

/** utility function that marries up a list of quantities with a list of positions into a record/dictionary
*
* @param { quantity[] } quants
* @param { number [] } positions
* @returns { sylMap }
*/
export function marryUp(quants: quantity[], positions: number[]): sylMap {
let output: sylMap = {};
let breaks = 0;
for (let i = 0; i < quants.length; i++) {
let curQuant = quants[i];
let curPos: number;
if (curQuant === "break") {
breaks++;
curPos = positions[i - breaks] + 1;
} else {
curPos = positions[i - breaks];
}
output[curPos] = curQuant;
}
return output;
}

export let insertPunctuation = (
line: string[],
markup: Record<number, string>
): string[] => {
let positions = Object.keys(markup).map((el) => parseInt(el));
for (let each of positions) {
line.splice(each, 0, markup[each]);
}
return line;
};

/**
* hexScan matches the possible scans to the known quantities
* returns an array of objects
Expand Down Expand Up @@ -267,7 +384,7 @@ export let hexScan = (map: sylMap): quantity[][] => {
return meters;
}

meters = arrToQuantity(generateHexCombos(dactyls));
meters = arrToQuantity(generateHexCombos(dactyls), "Hexameter");
//create a copy of the meters without breaks
let clone = meters.map((each) => {
return each.filter((elt) => {
Expand All @@ -293,72 +410,58 @@ export let hexScan = (map: sylMap): quantity[][] => {
return meters;
};

/** function that takes a list of permutator outputs (4 binary arrays) and returns a list of complete quantity descriptions; 1 for each arr in the input.
*
* @param { number[][] } arr
* @returns { quantity[][] }
*/
export function arrToQuantity(arr: number[][]): quantity[][] {
let output: quantity[][] = [];
for (let each of arr) {
let temp = each.map((el) => {
//first we map each 0 or 1 to an array of quantities.
return el === 0 //if the element is 0, then the foot is long
? (["long", "long", "break"] as quantity[]) //so insert the long foot template
: (["long", "short", "short", "break"] as quantity[]); //else, insert the short foot template
});

//we have now an array of quantity arrays; (quantity[][])
temp.push([
"long",
"short",
"short",
"break",
"long",
"undefined",
] as quantity[]);
export let penScan = (map: sylMap): quantity[][] => {
function generatePenCombos(dactyls: number): number[][] {
switch (dactyls) {
case 0:
return [[0, 0]];
case 1:
return [
[0, 1],
[1, 0],
];
case 2:
return [[1, 1]];
}
return [[0, 0]]; //the default case is to assume 0 dactyls
}
let quantValues = Object.values(map); //extract quantities array
let meters: quantity[][] = [];

//we then flatten this by concatenating all the inner lists
//resulting in a quant[]
let temp2 = temp.reduce((acc, val) => {
return acc.concat(val);
});
//now, calculate the number of spondaic syllables
let vowels = quantValues.length;
let dactyls = vowels - 12;

output.push(temp2); //push this to the list of meters
//handle line too long or short cases
if (dactyls > 2) {
console.log("too long!");
return meters;
} else if (dactyls < 0) {
console.log("too short!");
return meters;
}
return output;
}

/** utility function that marries up a list of quantities with a list of positions into a record/dictionary
*
* @param { quantity[] } quants
* @param { number [] } positions
* @returns { sylMap }
*/
export function marryUp(quants: quantity[], positions: number[]): sylMap {
let output: sylMap = {};
let breaks = 0;
for (let i = 0; i < quants.length; i++) {
let curQuant = quants[i];
let curPos: number;
if (curQuant === "break") {
breaks++;
curPos = positions[i - breaks] + 1;
} else {
curPos = positions[i - breaks];
meters = arrToQuantity(generatePenCombos(dactyls), "Pentameter");
//create a copy of the meters without breaks
let clone = meters.map((each) => {
return each.filter((elt) => {
return elt !== "break";
});
});
let curQuant: quantity;
for (let vowelCounter = 0; vowelCounter < vowels; vowelCounter++) {
curQuant = quantValues[vowelCounter];
if (curQuant !== "undefined") {
for (let meterCounter = 0; meterCounter < meters.length; meterCounter++) {
if (clone[meterCounter][vowelCounter] === "undefined") {
// do nothing.
} else if (clone[meterCounter][vowelCounter] !== curQuant) {
clone.splice(meterCounter, 1);
meters.splice(meterCounter, 1);
meterCounter--;
}
}
}
output[curPos] = curQuant;
}
return output;
}

export let insertPunctuation = (
line: string[],
markup: Record<number, string>
): string[] => {
let positions = Object.keys(markup).map((el) => parseInt(el));
for (let each of positions) {
line.splice(each, 0, markup[each]);
}
return line;
return meters;
};
3 changes: 2 additions & 1 deletion src/scanTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ export type metaLine = {
export type sylMap = Record<number, quantity>;
export type generalRecord = Record<number, string>;

export type meter = "hexameter" | "pentameter" | "elegaic";
export type meter = "Hexameter" | "Pentameter" | "Elegaic";

export type setting = {
meter: meter;
first: meter;
};

export type strictQuant = "long" | "short";
Expand Down
Loading

0 comments on commit 06c899a

Please sign in to comment.