Skip to content

Instantly share code, notes, and snippets.

@kenwebb

kenwebb/CouponDog.c

Last active Dec 29, 2020
Embed
What would you like to do?
Grokking Simplicity - book by Eric Normand

This gist explores an example from Grokking Simplicity, a book by Eric Normand.

/*
https://livebook.manning.com/book/grokking-simplicity/chapter-3/v-9/
See my Xholon workbook: Grokking Simplicity - book by Eric Normand
cd ~/gwtspace/Xholon/workbook/groksimpl/coupondog
gcc -o CouponDog.out CouponDog.c
./CouponDog.out
*/
#include <stdio.h>
#include <string.h>
#define GOOD "good"
#define BEST "best"
#define BAD "bad"
// function prototypes ---------------------------------------------------
void initDbA();
struct subscriber *fetchSubscribersFromDbA();
struct coupon *fetchCouponsFromDbA();
struct coupon *selectCouponsByRankC(struct coupon *coupons, char *rank);
struct coupon *selectBestCouponsC(struct coupon *coupons);
struct coupon *selectGoodCouponsC(struct coupon *coupons);
char *decideCouponRankC(struct subscriber subscriber);
struct email planEmailC(struct subscriber subscriber, char *couponRank, struct coupon *coupons);
struct email planEmailForSubscriberC(struct subscriber subscriber, struct coupon *goods, struct coupon *bests);
struct email *planListOfEmailsC(struct subscriber *subscribers, struct coupon *goods, struct coupon *bests);
char *toJSONC(struct email *emails);
void sendEmailsA(char *json);
// struct definitions ----------------------------------------------------
struct subscriber {
char *email;
int rec_count;
};
struct coupon {
char coupon[20];
char rank[5];
};
struct db {
struct subscriber *subscribers;
struct coupon *coupons;
};
struct email {
char from[30];
char to[30];
char subject[50];
char body[100];
};
// extern definitions ----------------------------------------------------
struct subscriber subscribers[] = {
"john@coldmail.com",2,
"sam@pmail.co",16,
"linda1989@oal.com",1,
"jan1940@ahoy.com",0,
"mrbig@pmail.co",25,
"lol@lol.lol",0
};
struct coupon coupons[] = {
"MAYDISCOUNT",GOOD,
"10PERCENT",BAD,
"PROMOTION45",BEST,
"IHEARTYOU",BAD,
"GETADEAL",BEST,
"ILIKEDISCOUNTS",GOOD
};
struct db dbD;
struct coupon rbests[] = {"","", "","", "","", "","", "","", "",""};
struct coupon rgoods[] = {"","", "","", "","", "","", "","", "",""};
struct email email;
struct email emails[10];
char json[1000];
// Populate Database ----------------------------------------------------------
void initDbA() {
extern struct subscriber subscribers[];
extern struct coupon coupons[];
extern struct db dbD;
dbD.subscribers = subscribers;
dbD.coupons = coupons;
}
// Fetch Lists from Database ---------------------------------------------------
struct subscriber *fetchSubscribersFromDbA() {
extern struct db dbD;
return dbD.subscribers;
}
struct coupon *fetchCouponsFromDbA() {
extern struct db dbD;
return dbD.coupons;
}
// Select Coupons --------------------------------------------------------------
struct coupon *selectCouponsByRankC(struct coupon *coupons, char *rank) {
extern struct coupon rbests[];
extern struct coupon rgoods[];
int ix = 0;
struct coupon *ranked = strcmp(rank, BEST) ? rbests : rgoods;
for (int c = 0; c < sizeof(coupons); c++) {
strcpy(ranked[c].coupon, "");
strcpy(ranked[c].rank, "");
struct coupon coupon = coupons[c];
if (strcmp(coupon.rank, rank) == 0) {
strcpy(ranked[ix].coupon, coupon.coupon);
strcpy(ranked[ix].rank, coupon.rank);
ix++;
}
}
return ranked;
}
struct coupon *selectBestCouponsC(struct coupon *coupons) {
return selectCouponsByRankC(coupons, BEST);
}
struct coupon *selectGoodCouponsC(struct coupon *coupons) {
return selectCouponsByRankC(coupons, GOOD);
}
char *decideCouponRankC(struct subscriber subscriber) {
if (subscriber.rec_count >= 10) {
return BEST;
}
else {
return GOOD;
}
}
// Prepare and Send Emails -----------------------------------------------------
struct email planEmailC(struct subscriber subscriber, char *couponRank, struct coupon *coupons) {
extern struct email email;
sprintf(email.from, "%s", "newsletter@coupondog.co");
sprintf(email.to, "%s", subscriber.email);
sprintf(email.subject, "%s%s%s", "Your ", couponRank, " weekly coupons inside");
char cstr[70];
cstr[0] = '\0';
for (int i = 0; i < sizeof(coupons); i++) {
if (coupons[i].coupon[0] != '\0') {
strcat(cstr, coupons[i].coupon);
strcat(cstr, " ");
}
}
sprintf(email.body, "%s%s%s%s", "Here are the ", couponRank, " coupons: ", cstr);
return email;
}
struct email planEmailForSubscriberC(struct subscriber subscriber, struct coupon *goods, struct coupon *bests) {
char *rank = decideCouponRankC(subscriber);
if (strcmp(rank, BEST) == '\0') {
return planEmailC(subscriber, BEST, bests);
}
else if (strcmp(rank, GOOD) == '\0') {
return planEmailC(subscriber, GOOD, goods);
}
else {
return planEmailC(subscriber, BAD, goods);
}
}
struct email *planListOfEmailsC(struct subscriber *subscribers, struct coupon *goods, struct coupon *bests) {
extern struct email emails[];
for (int i = 0; i < sizeof(subscribers); i++) {
struct subscriber subscriber = subscribers[i];
struct email email_ = planEmailForSubscriberC(subscriber, goods, bests);
emails[i] = email_;
}
return emails;
}
char *toJSONC(struct email *emails) {
extern char json[];
json[0] = '\0';
strcat(json, "[\n");
for (int i = 0; i < sizeof(emails); i++) {
struct email email_ = emails[i];
if (strcmp(email_.to, "(null)") != 0) { // ???
strcat(json, " {");
strcat(json, "\n \"from\": \"");
strcat(json, email_.from);
strcat(json, "\",\n \"to\": \"");
strcat(json, email_.to);
strcat(json, "\",\n \"subject\": \"");
strcat(json, email_.subject);
strcat(json, "\",\n \"body\": \"");
strcat(json, email_.body);
strcat(json, "\"\n },\n");
}
}
strcat(json, "]\n");
return json;
}
void sendEmailsA(char *json) {
printf("%s\n", json);
}
// MAIN -----------------------------------------------------------------
int main() {
initDbA();
struct subscriber *listOfSubscribersD = fetchSubscribersFromDbA();
struct coupon *listOfCouponsD = fetchCouponsFromDbA();
struct coupon *bestsD = selectBestCouponsC(listOfCouponsD);
struct coupon *goodsD = selectGoodCouponsC(listOfCouponsD);
struct email *listOfEmailsD = planListOfEmailsC(
listOfSubscribersD,
goodsD,
bestsD
);
char *jsonD = toJSONC(listOfEmailsD);
sendEmailsA(jsonD);
return 0;
}
<script><![CDATA[
/*
This is an implementation of the CouponDog example app in chapter three of the book:
Eric Normand, "Grokking Simplicity: Taming complex software with functional thinking",
MEAP began August 2019 Publication in Spring 2021 (estimated),
ISBN 9781617296208 325 pages (estimated)
https://livebook.manning.com/book/grokking-simplicity/chapter-3/v-9/
This JavaScript implementation is by Ken Webb.
December 8, 2020
ken@primordion.com
Legend
------
As per usage in the Grokking Simplicity book, the name of every const in my JavaScript code, ends in the letter A, C, or D.
A Action
C Calculation
D Data
As much as possible, I use the same function and data names as Eric uses in the example in his book.
All of the calculation (C) functions are preceeded by a Signature as a JavaScript comment.
The signature syntax is based on the Hindley-Milner syntax used in ramdajs (https://ramdajs.com/).
My Goal
-------
I am learning to use Functional Programming (FP) techniques in the latest versions of JavaScript.
I've found this to be a good exercise in support of my learning.
The following code works using Firefox and Chrome Dev Tools.
*/
//clear();
(() => {
// constants
const BEST = "best"
const GOOD = "good"
const BAD = "bad"
const RANK_CUTOFF = 10
// Populate Database ----------------------------------------------------------
// str2arrC :: String -> String -> [String]
const str2arrC = (sep) => (str) => str.split(sep)
const str2arrNlC = str2arrC("\n")
const str2arrCmC = str2arrC(",")
// Email database table
// email,rec_count
const subscribersRawD =
`john@coldmail.com,2
sam@pmail.co,16
linda1989@oal.com,1
jan1940@ahoy.com,0
mrbig@pmail.co,25
lol@lol.lol,0`;
// Coupon database table
// coupon,rank
const couponsRawD =
`MAYDISCOUNT,good
10PERCENT,bad
PROMOTION45,best
IHEARTYOU,bad
GETADEAL,best
ILIKEDISCOUNTS,good`
// raw2jsoC :: (String, String, String) -> Object
const raw2jsoC = (hdr1, hdr2, raw) => str2arrNlC(raw).map((str) => {
const [data1, data2] = str2arrCmC(str)
return {[hdr1]: data1, [hdr2]: data2}
})
const dbD = {}
dbD.subscribers = raw2jsoC("email", "rec_count", subscribersRawD)
dbD.coupons = raw2jsoC("coupon", "rank", couponsRawD)
// Fetch Lists from Database ---------------------------------------------------
// fetchSubscribersFromDbA :: () -> [Object]
const fetchSubscribersFromDbA = () => dbD.subscribers
const fetchCouponsFromDbA = () => dbD.coupons
const listOfSubscribersD = fetchSubscribersFromDbA()
const listOfCouponsD = fetchCouponsFromDbA()
// Select Coupons --------------------------------------------------------------
// selectCouponsByRankC :: String -> [Object] -> [String]
const selectCouponsByRankC = rank => coupons => coupons.reduce((ret, coupon) =>
(coupon.rank === rank) ? ret.concat([coupon.coupon]) : ret, [])
const selectBestCouponsC = selectCouponsByRankC(BEST)
const selectGoodCouponsC = selectCouponsByRankC(GOOD)
//const selectBadCouponsC = selectCouponsByRankC(BAD)
// decideCouponRankC :: Object -> String
const decideCouponRankC = (subscriber) => subscriber.rec_count >= RANK_CUTOFF ? BEST : GOOD
// Prepare and Send Emails -----------------------------------------------------
// planEmailC :: (Object, String, [String]) -> Object
const planEmailC = (subscriber, couponRank, coupons) => ({
from: "newsletter@coupondog.co",
to: subscriber.email,
subject: `Your ${couponRank} weekly coupons inside`,
body: `Here are the ${couponRank} coupons: ` + coupons.join(", ")
})
// planEmailForSubscriberC :: (Object, [String], [String]) -> Object
const planEmailForSubscriberC = (subscriber, goods, bests) => {
switch (decideCouponRankC(subscriber)) {
case GOOD: return planEmailC(subscriber, GOOD, goods)
case BEST: return planEmailC(subscriber, BEST, bests)
default: return {};
}
}
// planListOfEmailsC :: ([Object], [Object]) -> [Object]
const planListOfEmailsC = (subscribers, coupons) => subscribers.map((subscriber) =>
planEmailForSubscriberC(
subscriber,
selectGoodCouponsC(coupons),
selectBestCouponsC(coupons)
)
)
const listOfEmailsD = planListOfEmailsC(listOfSubscribersD, listOfCouponsD)
const sendEmailsA = (emails) => console.log(emails)
sendEmailsA(listOfEmailsD)
if ($wnd.xh) {
$wnd.xh.root().println(JSON.stringify(listOfEmailsD, null, 2))
}
})()
]]></script>
package org.primordion.user.app.groksimpl.ch03;
import java.util.ArrayList;
import java.util.List;
/**
* Coupon Dog.
* based on: https://gist.github.com/kenwebb/6424d56a48695ad96175a20ef48394ed CouponDog.js
* https://www.manning.com/books/grokking-simplicity
* @author <a href="mailto:ken@primordion.com">Ken Webb</a>
* @see <a href="http://www.primordion.com/Xholon">Xholon Project website</a>
* @see <a href="https://gist.github.com/kenwebb/6424d56a48695ad96175a20ef48394ed">Coupon Dog workbook Grokking Simplicity - book by Eric Normand</a>
* @since 0.9.1 (Created on December 28, 2020
*/
public class CouponDog {
// Populate Database ----------------------------------------------------------
// Email database table
// email,rec_count
private static final String subscribersRawD =
"john@coldmail.com,2\n" +
"sam@pmail.co,16\n" +
"linda1989@oal.com,1\n" +
"jan1940@ahoy.com,0\n" +
"mrbig@pmail.co,25\n" +
"lol@lol.lol,0";
// Coupon database table
// coupon,rank
private static final String couponsRawD =
"MAYDISCOUNT,good\n" +
"10PERCENT,bad\n" +
"PROMOTION45,best\n" +
"IHEARTYOU,bad\n" +
"GETADEAL,best\n" +
"ILIKEDISCOUNTS,good";
protected class Subscriber {
String email = null;
int rec_count = 0;
}
protected class Coupon {
String coupon = null;
String rank = null;
}
protected class Db {
List<Subscriber> subscribers = null;
List<Coupon> coupons = null;
}
protected class Email {
String from = null;
String to = null;
String subject = null;
String body = null;
}
private final Db dbD = new Db();
public void act() {
dbD.subscribers = raw2listofsubC(subscribersRawD);
dbD.coupons = raw2listofcpnC(couponsRawD);
List<Subscriber> listOfSubscribersD = fetchSubscribersFromDbA();
List<Coupon> listOfCouponsD = fetchCouponsFromDbA();
List<String> listOfEmailsD = planListOfEmailsC(
listOfSubscribersD,
selectGoodCouponsC(listOfCouponsD),
selectBestCouponsC(listOfCouponsD)
);
sendEmailsA(listOfEmailsD);
}
protected List<Subscriber> raw2listofsubC(String raw) {
List<Subscriber> list = new ArrayList<Subscriber>();
String[] lines = raw.split("\n");
for (int i = 0; i < lines.length; i++) {
String[] arr = lines[i].split(",");
String data1 = arr[0];
String data2 = arr[1];
Subscriber sub = new Subscriber();
sub.email = data1;
sub.rec_count = Integer.parseInt(data2);
list.add(sub);
}
return list;
}
protected List<Coupon> raw2listofcpnC(String raw) {
List<Coupon> list = new ArrayList<Coupon>();
String[] lines = raw.split("\n");
for (int i = 0; i < lines.length; i++) {
String[] arr = lines[i].split(",");
String data1 = arr[0];
String data2 = arr[1];
Coupon cpn = new Coupon();
cpn.coupon = data1;
cpn.rank = data2;
list.add(cpn);
}
return list;
}
// Fetch Lists from Database ---------------------------------------------------
protected List<Subscriber> fetchSubscribersFromDbA() {return dbD.subscribers;}
protected List<Coupon> fetchCouponsFromDbA() {return dbD.coupons;}
// Select Coupons --------------------------------------------------------------
protected List<String> selectCouponsByRankC(List<Coupon> coupons, String rank) {
List<String> ret = new ArrayList<String>();
for (int c = 0; c < coupons.size(); c++) {
Coupon coupon = coupons.get(c);
if (rank.equals(coupon.rank))
ret.add(coupon.coupon);
}
return ret;
}
protected List<String> selectBestCouponsC(List<Coupon> coupons) {
return selectCouponsByRankC(coupons, "best");
}
protected List<String> selectGoodCouponsC(List<Coupon> coupons) {
return selectCouponsByRankC(coupons, "good");
}
protected String decideCouponRankC(Subscriber subscriber) {
if (subscriber.rec_count >= 10) {
return "best";
}
else {
return "good";
}
}
// Prepare and Send Emails -----------------------------------------------------
protected String planEmailC(Subscriber subscriber, String couponRank, List<String> coupons) {
return "{\n"
+ " from: " + "\"newsletter@coupondog.co\"" + ",\n"
+ " to: \"" + subscriber.email + "\",\n"
+ " subject: \"" + "Your " + couponRank + " weekly coupons inside" + "\",\n"
+ " body: \"" + "Here are the " + couponRank + " coupons: " + String.join(", ", coupons) + "\"\n"
+ "}\n";
}
protected String planEmailForSubscriberC(Subscriber subscriber, List<String> goods, List<String> bests) {
String rank = decideCouponRankC(subscriber);
if ("best".equals(rank)) {
return planEmailC(subscriber, "good", goods);
}
else if ("good".equals(rank)) {
return planEmailC(subscriber, "best", bests);
}
else {
return null;
}
}
protected List<String> planListOfEmailsC(List<Subscriber> subscribers, List<String> goods, List<String> bests) {
List<String> emails = new ArrayList<String>();
for (int s = 0; s < subscribers.size(); s++) {
Subscriber subscriber = subscribers.get(s);
String email = planEmailForSubscriberC(subscriber, goods, bests);
emails.add(email);
}
return emails;
}
protected void sendEmailsA(List<String> emails) {
consoleLog(emails);
System.out.println(emails);
}
protected native void consoleLog(Object obj) /*-{
$wnd.console.log(obj);
}-*/;
public static void main(String[] args) {
CouponDog couponDog = new CouponDog();
couponDog.act();
}
}
<script><![CDATA[
/*
Traditional JavaScript - more or less directly from the book
This is an implementation of the example app in chapter three of the book:
Eric Normand, "Grokking Simplicity: Taming complex software with functional thinking",
MEAP began August 2019 Publication in Spring 2021 (estimated),
ISBN 9781617296208 325 pages (estimated)
https://livebook.manning.com/book/grokking-simplicity/chapter-3/v-9/
This JavaScript implementation is by Ken Webb.
December 11, 2020
ken@primordion.com
Legend
------
As per usage in the Grokking Simplicity book, the name of every function or var in my JavaScript code, ends in the letter A, C, or D.
A Action
C Calculation
D Data
As much as possible, I use the same function and data names as Eric uses in the example in his book.
My Goal
-------
The following code works using Firefox and Chrome Dev Tools.
*/
//clear();
(function() {
// Populate Database ----------------------------------------------------------
// Email database table
// email,rec_count
var subscribersRawD =
"john@coldmail.com,2\n" +
"sam@pmail.co,16\n" +
"linda1989@oal.com,1\n" +
"jan1940@ahoy.com,0\n" +
"mrbig@pmail.co,25\n" +
"lol@lol.lol,0";
// Coupon database table
// coupon,rank
var couponsRawD =
"MAYDISCOUNT,good\n" +
"10PERCENT,bad\n" +
"PROMOTION45,best\n" +
"IHEARTYOU,bad\n" +
"GETADEAL,best\n" +
"ILIKEDISCOUNTS,good";
function raw2jsoC(hdr1, hdr2, raw) {
var jso = [];
var lines = raw.split("\n");
for (var i = 0; i < lines.length; i++) {
var arr = lines[i].split(",");
var data1 = arr[0];
var data2 = arr[1];
jso.push({[hdr1]: data1, [hdr2]: data2});
}
return jso;
}
var dbD = {}
dbD.subscribers = raw2jsoC("email", "rec_count", subscribersRawD)
dbD.coupons = raw2jsoC("coupon", "rank", couponsRawD)
// Fetch Lists from Database ---------------------------------------------------
function fetchSubscribersFromDbA() {return dbD.subscribers}
function fetchCouponsFromDbA() {return dbD.coupons}
var listOfSubscribersD = fetchSubscribersFromDbA()
var listOfCouponsD = fetchCouponsFromDbA()
// Select Coupons --------------------------------------------------------------
function selectCouponsByRankC(coupons, rank) {
var ret = [];
for (var c = 0; c < coupons.length; c++) {
var coupon = coupons[c];
if (coupon.rank === rank)
ret.push(coupon.coupon);
}
return ret;
}
function selectBestCouponsC(coupons) {
return selectCouponsByRankC(coupons, "best");
}
function selectGoodCouponsC(coupons) {
return selectCouponsByRankC(coupons, "good");
}
function decideCouponRankC(subscriber) {
if (subscriber.rec_count >= 10) {
return "best";
}
else {
return "good";
}
}
// Prepare and Send Emails -----------------------------------------------------
function planEmailC (subscriber, couponRank, coupons) {
return {
from: "newsletter@coupondog.co",
to: subscriber.email,
subject: "Your " + couponRank + " weekly coupons inside",
body: "Here are the " + couponRank + " coupons: " + coupons.join(", ")
}
}
function planEmailForSubscriberC(subscriber, goods, bests) {
var rank = decideCouponRankC(subscriber);
if (rank === "best")
return planEmailC(subscriber, "good", goods);
else if (rank == "good")
return planEmailC(subscriber, "best", bests)
}
function planListOfEmailsC(subscribers, goods, bests) {
var emails = [];
for (var s = 0; s < subscribers.length; s++) {
var subscriber = subscribers[s];
var email = planEmailForSubscriberC(subscriber, goods, bests);
emails.push(email);
}
return emails;
}
var listOfEmailsD = planListOfEmailsC(
listOfSubscribersD,
selectGoodCouponsC(listOfCouponsD),
selectBestCouponsC(listOfCouponsD)
)
function sendEmailsA(emails) {console.log(emails)}
sendEmailsA(listOfEmailsD)
if ($wnd.xh) {
$wnd.xh.root().println(JSON.stringify(listOfEmailsD, null, 2))
}
})()
]]></script>
<script><![CDATA[
/*
This is an implementation of the example app in chapter three of the book:
Eric Normand, "Grokking Simplicity: Taming complex software with functional thinking",
MEAP began August 2019 Publication in Spring 2021 (estimated),
ISBN 9781617296208 325 pages (estimated)
https://livebook.manning.com/book/grokking-simplicity/chapter-3/v-9/
This JavaScript implementation is by Ken Webb.
December 19, 2020
ken@primordion.com
This implementation requires Ramda "A practical functional library for JavaScript programmers."
https://ramdajs.com/
Legend
------
As per usage in the Grokking Simplicity book, the name of every const in my JavaScript code, ends in the letter A, C, or D.
A Action
C Calculation
D Data
As much as possible, I use the same function and data names as Eric uses in the example in his book.
All of the calculation (C) functions are preceeded by a Signature as a JavaScript comment.
The signature syntax is based on the Hindley-Milner syntax used in ramdajs (https://ramdajs.com/).
My Goal
-------
I am learning to use Functional Programming (FP) techniques in the latest versions of JavaScript.
I've found this to be a good exercise in support of my learning.
The following code works using Firefox and Chrome Dev Tools.
*/
//clear();
(() => {
// constants
const BEST = "best"
const GOOD = "good"
const BAD = "bad"
const RANK_CUTOFF = 10
// str2arrC :: String -> String -> [String]
const str2arrC = (sep) => (str) => str.split(sep)
const str2arrNlC = str2arrC("\n")
const str2arrCmC = str2arrC(",")
// arrOfStr2arrOfArrC :: [String] -> [[String]]
const arrOfStr2arrOfArrC = arr => arr.map(str => str2arrCmC(str))
// arrOfArr2ArrOfJsoC :: [[String]] -> [Object]
const arrOfArr2ArrOfJsoC = (hdr1, hdr2) => arr => arr.map(arr2 => ({[hdr1]: arr2[0], [hdr2]: arr2[1]}))
const arrOfJso2StrC = arrOfJso => arrOfJso.map(jso => jso.coupon);
// Email database table
// email,rec_count
const subscribersRawD =
`john@coldmail.com,2
sam@pmail.co,16
linda1989@oal.com,1
jan1940@ahoy.com,0
mrbig@pmail.co,25
lol@lol.lol,0`
// Coupon database table
// coupon,rank
const couponsRawD =
`MAYDISCOUNT,good
10PERCENT,bad
PROMOTION45,best
IHEARTYOU,bad
GETADEAL,best
ILIKEDISCOUNTS,good`
const trace = label => obj => {console.log(label, obj); return obj;}
// raw2jsoC :: (String, String) -> String) -> Object
const raw2jsoC = (hdr1, hdr2) => raw => R.compose(
//trace("four"),
arrOfArr2ArrOfJsoC(hdr1, hdr2),
//trace("three"),
arrOfStr2arrOfArrC,
//trace("two"),
str2arrNlC,
//trace("one")
)
// TODO why do I need the extra () in the middle?
const dbD = {
subscribers: raw2jsoC("email", "rec_count")()(subscribersRawD),
coupons: raw2jsoC("coupon", "rank")()(couponsRawD)
}
const [bestCouponsD, goodCouponsD] = R.compose(
R.partition(R.propEq('rank', BEST)),
R.filter(R.complement(R.propEq('rank', BAD)))
)(dbD.coupons)
//console.log(bestCouponsD, goodCouponsD);
// Fetch Lists from Database ---------------------------------------------------
// fetchSubscribersFromDbA :: () -> [Object]
const fetchSubscribersFromDbA = () => dbD.subscribers
const fetchCouponsFromDbA = () => dbD.coupons
const listOfSubscribersD = fetchSubscribersFromDbA()
const listOfCouponsD = fetchCouponsFromDbA()
// decideCouponRankC :: Object -> String
const decideCouponRankC = (subscriber) => subscriber.rec_count >= RANK_CUTOFF ? BEST : GOOD
// Prepare and Send Emails -----------------------------------------------------
// planEmailC :: (Object, String, [String]) -> Object
const planEmailC = (subscriber, couponRank, coupons) => ({
from: "newsletter@coupondog.co",
to: subscriber.email,
subject: `Your ${couponRank} weekly coupons inside`,
body: `Here are the ${couponRank} coupons: ` + arrOfJso2StrC(coupons).join(", ")
})
// planEmailForSubscriberC :: (Object, [String], [String]) -> Object
const planEmailForSubscriberC = (subscriber, goods, bests) => {
switch (decideCouponRankC(subscriber)) {
case GOOD: return planEmailC(subscriber, GOOD, goods)
case BEST: return planEmailC(subscriber, BEST, bests)
default: return {};
}
}
// planListOfEmailsC :: ([Object], [Object]) -> [Object]
const planListOfEmailsC = (subscribers, coupons) => subscribers.map((subscriber) =>
planEmailForSubscriberC(
subscriber,
goodCouponsD,
bestCouponsD
)
)
const listOfEmailsD = planListOfEmailsC(listOfSubscribersD, listOfCouponsD)
const sendEmailsA = (emails) => console.log(emails)
sendEmailsA(listOfEmailsD)
var $wnd = $wnd || window;
if ($wnd.xh) {
$wnd.xh.root().println(JSON.stringify(listOfEmailsD, null, 2))
}
})()
]]></script>
.file "CouponDog.c"
.text
.globl subscribers
.section .rodata
.LC0:
.string "john@coldmail.com"
.LC1:
.string "sam@pmail.co"
.LC2:
.string "linda1989@oal.com"
.LC3:
.string "jan1940@ahoy.com"
.LC4:
.string "mrbig@pmail.co"
.LC5:
.string "lol@lol.lol"
.section .data.rel.local,"aw"
.align 32
.type subscribers, @object
.size subscribers, 96
subscribers:
.quad .LC0
.long 2
.zero 4
.quad .LC1
.long 16
.zero 4
.quad .LC2
.long 1
.zero 4
.quad .LC3
.long 0
.zero 4
.quad .LC4
.long 25
.zero 4
.quad .LC5
.long 0
.zero 4
.globl coupons
.data
.align 32
.type coupons, @object
.size coupons, 150
coupons:
.string "MAYDISCOUNT"
.zero 8
.string "good"
.string "10PERCENT"
.zero 10
.string "bad"
.zero 1
.string "PROMOTION45"
.zero 8
.string "best"
.string "IHEARTYOU"
.zero 10
.string "bad"
.zero 1
.string "GETADEAL"
.zero 11
.string "best"
.string "ILIKEDISCOUNTS"
.zero 5
.string "good"
.comm dbD,16,16
.globl rbests
.bss
.align 32
.type rbests, @object
.size rbests, 150
rbests:
.zero 150
.globl rgoods
.align 32
.type rgoods, @object
.size rgoods, 150
rgoods:
.zero 150
.comm email,210,32
.comm emails,2100,32
.comm json,1000,32
.text
.globl initDbA
.type initDbA, @function
initDbA:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq subscribers(%rip), %rax
movq %rax, dbD(%rip)
leaq coupons(%rip), %rax
movq %rax, 8+dbD(%rip)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size initDbA, .-initDbA
.globl fetchSubscribersFromDbA
.type fetchSubscribersFromDbA, @function
fetchSubscribersFromDbA:
.LFB1:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq dbD(%rip), %rax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size fetchSubscribersFromDbA, .-fetchSubscribersFromDbA
.globl fetchCouponsFromDbA
.type fetchCouponsFromDbA, @function
fetchCouponsFromDbA:
.LFB2:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq 8+dbD(%rip), %rax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size fetchCouponsFromDbA, .-fetchCouponsFromDbA
.section .rodata
.LC6:
.string "best"
.text
.globl selectCouponsByRankC
.type selectCouponsByRankC, @function
selectCouponsByRankC:
.LFB3:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $88, %rsp
.cfi_offset 3, -24
movq %rdi, -88(%rbp)
movq %rsi, -96(%rbp)
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
movl $0, -80(%rbp)
movq -96(%rbp), %rax
leaq .LC6(%rip), %rsi
movq %rax, %rdi
call strcmp@PLT
testl %eax, %eax
je .L7
leaq rbests(%rip), %rax
jmp .L8
.L7:
leaq rgoods(%rip), %rax
.L8:
movq %rax, -72(%rbp)
movl $0, -76(%rbp)
jmp .L9
.L11:
movl -76(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -72(%rbp), %rax
addq %rdx, %rax
movb $0, (%rax)
movl -76(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -72(%rbp), %rax
addq %rdx, %rax
addq $20, %rax
movb $0, (%rax)
movl -76(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -88(%rbp), %rax
addq %rdx, %rax
movq (%rax), %rcx
movq 8(%rax), %rbx
movq %rcx, -64(%rbp)
movq %rbx, -56(%rbp)
movq 16(%rax), %rdx
movq %rdx, -48(%rbp)
movzbl 24(%rax), %eax
movb %al, -40(%rbp)
movq -96(%rbp), %rax
leaq -64(%rbp), %rdx
addq $20, %rdx
movq %rax, %rsi
movq %rdx, %rdi
call strcmp@PLT
testl %eax, %eax
jne .L10
movl -80(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -72(%rbp), %rax
addq %rdx, %rax
movq %rax, %rdx
leaq -64(%rbp), %rax
movq %rax, %rsi
movq %rdx, %rdi
call strcpy@PLT
movl -80(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -72(%rbp), %rax
addq %rdx, %rax
addq $20, %rax
leaq -64(%rbp), %rdx
addq $20, %rdx
movq %rdx, %rsi
movq %rax, %rdi
call strcpy@PLT
addl $1, -80(%rbp)
.L10:
addl $1, -76(%rbp)
.L9:
movl -76(%rbp), %eax
cmpl $7, %eax
jbe .L11
movq -72(%rbp), %rax
movq -24(%rbp), %rbx
xorq %fs:40, %rbx
je .L13
call __stack_chk_fail@PLT
.L13:
addq $88, %rsp
popq %rbx
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE3:
.size selectCouponsByRankC, .-selectCouponsByRankC
.globl selectBestCouponsC
.type selectBestCouponsC, @function
selectBestCouponsC:
.LFB4:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
leaq .LC6(%rip), %rsi
movq %rax, %rdi
call selectCouponsByRankC
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE4:
.size selectBestCouponsC, .-selectBestCouponsC
.section .rodata
.LC7:
.string "good"
.text
.globl selectGoodCouponsC
.type selectGoodCouponsC, @function
selectGoodCouponsC:
.LFB5:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
leaq .LC7(%rip), %rsi
movq %rax, %rdi
call selectCouponsByRankC
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE5:
.size selectGoodCouponsC, .-selectGoodCouponsC
.globl decideCouponRankC
.type decideCouponRankC, @function
decideCouponRankC:
.LFB6:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, %rax
movq %rsi, %rcx
movq %rcx, %rdx
movq %rax, -16(%rbp)
movq %rdx, -8(%rbp)
movl -8(%rbp), %eax
cmpl $9, %eax
jle .L19
leaq .LC6(%rip), %rax
jmp .L20
.L19:
leaq .LC7(%rip), %rax
.L20:
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size decideCouponRankC, .-decideCouponRankC
.section .rodata
.LC8:
.string "newsletter@coupondog.co"
.LC9:
.string "%s"
.LC10:
.string " weekly coupons inside"
.LC11:
.string "Your "
.LC12:
.string "%s%s%s"
.LC13:
.string " coupons: "
.LC14:
.string "Here are the "
.LC15:
.string "%s%s%s%s"
.text
.globl planEmailC
.type planEmailC, @function
planEmailC:
.LFB7:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $152, %rsp
.cfi_offset 3, -24
movq %rdi, -120(%rbp)
movq %rsi, %rax
movq %rdx, %rsi
movq %rsi, %rdx
movq %rax, -144(%rbp)
movq %rdx, -136(%rbp)
movq %rcx, -128(%rbp)
movq %r8, -152(%rbp)
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
leaq .LC8(%rip), %rdx
leaq .LC9(%rip), %rsi
leaq email(%rip), %rdi
movl $0, %eax
call sprintf@PLT
movq -144(%rbp), %rax
movq %rax, %rdx
leaq .LC9(%rip), %rsi
leaq 30+email(%rip), %rdi
movl $0, %eax
call sprintf@PLT
movq -128(%rbp), %rax
leaq .LC10(%rip), %r8
movq %rax, %rcx
leaq .LC11(%rip), %rdx
leaq .LC12(%rip), %rsi
leaq 60+email(%rip), %rdi
movl $0, %eax
call sprintf@PLT
movb $0, -96(%rbp)
movl $0, -100(%rbp)
jmp .L22
.L24:
movl -100(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -152(%rbp), %rax
addq %rdx, %rax
movzbl (%rax), %eax
testb %al, %al
je .L23
movl -100(%rbp), %eax
movslq %eax, %rdx
movq %rdx, %rax
salq $2, %rax
addq %rdx, %rax
leaq 0(,%rax,4), %rdx
addq %rax, %rdx
movq -152(%rbp), %rax
addq %rdx, %rax
movq %rax, %rdx
leaq -96(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call strcat@PLT
leaq -96(%rbp), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq -96(%rbp), %rax
addq %rdx, %rax
movw $32, (%rax)
.L23:
addl $1, -100(%rbp)
.L22:
movl -100(%rbp), %eax
cmpl $7, %eax
jbe .L24
leaq -96(%rbp), %rdx
movq -128(%rbp), %rax
movq %rdx, %r9
leaq .LC13(%rip), %r8
movq %rax, %rcx
leaq .LC14(%rip), %rdx
leaq .LC15(%rip), %rsi
leaq 110+email(%rip), %rdi
movl $0, %eax
call sprintf@PLT
movq -120(%rbp), %rax
movq email(%rip), %rcx
movq 8+email(%rip), %rbx
movq %rcx, (%rax)
movq %rbx, 8(%rax)
movq 16+email(%rip), %rcx
movq 24+email(%rip), %rbx
movq %rcx, 16(%rax)
movq %rbx, 24(%rax)
movq 32+email(%rip), %rcx
movq 40+email(%rip), %rbx
movq %rcx, 32(%rax)
movq %rbx, 40(%rax)
movq 48+email(%rip), %rcx
movq 56+email(%rip), %rbx
movq %rcx, 48(%rax)
movq %rbx, 56(%rax)
movq 64+email(%rip), %rcx
movq 72+email(%rip), %rbx
movq %rcx, 64(%rax)
movq %rbx, 72(%rax)
movq 80+email(%rip), %rcx
movq 88+email(%rip), %rbx
movq %rcx, 80(%rax)
movq %rbx, 88(%rax)
movq 96+email(%rip), %rcx
movq 104+email(%rip), %rbx
movq %rcx, 96(%rax)
movq %rbx, 104(%rax)
movq 112+email(%rip), %rcx
movq 120+email(%rip), %rbx
movq %rcx, 112(%rax)
movq %rbx, 120(%rax)
movq 128+email(%rip), %rcx
movq 136+email(%rip), %rbx
movq %rcx, 128(%rax)
movq %rbx, 136(%rax)
movq 144+email(%rip), %rcx
movq 152+email(%rip), %rbx
movq %rcx, 144(%rax)
movq %rbx, 152(%rax)
movq 160+email(%rip), %rcx
movq 168+email(%rip), %rbx
movq %rcx, 160(%rax)
movq %rbx, 168(%rax)
movq 176+email(%rip), %rcx
movq 184+email(%rip), %rbx
movq %rcx, 176(%rax)
movq %rbx, 184(%rax)
movq 192+email(%rip), %rcx
movq 200+email(%rip), %rbx
movq %rcx, 192(%rax)
movq %rbx, 200(%rax)
movzwl 208+email(%rip), %edx
movw %dx, 208(%rax)
movq -24(%rbp), %rax
xorq %fs:40, %rax
je .L26
call __stack_chk_fail@PLT
.L26:
movq -120(%rbp), %rax
addq $152, %rsp
popq %rbx
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE7:
.size planEmailC, .-planEmailC
.section .rodata
.LC16:
.string "bad"
.text
.globl planEmailForSubscriberC
.type planEmailForSubscriberC, @function
planEmailForSubscriberC:
.LFB8:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $64, %rsp
movq %rdi, -24(%rbp)
movq %rsi, %rax
movq %rdx, %rsi
movq %rsi, %rdx
movq %rax, -48(%rbp)
movq %rdx, -40(%rbp)
movq %rcx, -32(%rbp)
movq %r8, -56(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq -48(%rbp), %rdx
movq -40(%rbp), %rax
movq %rdx, %rdi
movq %rax, %rsi
call decideCouponRankC
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
leaq .LC6(%rip), %rsi
movq %rax, %rdi
call strcmp@PLT
testl %eax, %eax
jne .L28
movq -24(%rbp), %rax
movq -56(%rbp), %rcx
movq -48(%rbp), %rsi
movq -40(%rbp), %rdx
movq %rcx, %r8
leaq .LC6(%rip), %rcx
movq %rax, %rdi
call planEmailC
jmp .L27
.L28:
movq -16(%rbp), %rax
leaq .LC7(%rip), %rsi
movq %rax, %rdi
call strcmp@PLT
testl %eax, %eax
jne .L30
movq -24(%rbp), %rax
movq -32(%rbp), %rcx
movq -48(%rbp), %rsi
movq -40(%rbp), %rdx
movq %rcx, %r8
leaq .LC7(%rip), %rcx
movq %rax, %rdi
call planEmailC
jmp .L27
.L30:
movq -24(%rbp), %rax
movq -32(%rbp), %rcx
movq -48(%rbp), %rsi
movq -40(%rbp), %rdx
movq %rcx, %r8
leaq .LC16(%rip), %rcx
movq %rax, %rdi
call planEmailC
.L27:
movq -8(%rbp), %rax
xorq %fs:40, %rax
je .L31
call __stack_chk_fail@PLT
.L31:
movq -24(%rbp), %rax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE8:
.size planEmailForSubscriberC, .-planEmailForSubscriberC
.globl planListOfEmailsC
.type planListOfEmailsC, @function
planListOfEmailsC:
.LFB9:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $296, %rsp
.cfi_offset 3, -24
movq %rdi, -280(%rbp)
movq %rsi, -288(%rbp)
movq %rdx, -296(%rbp)
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
movl $0, -260(%rbp)
jmp .L33
.L34:
movl -260(%rbp), %eax
cltq
salq $4, %rax
movq %rax, %rdx
movq -280(%rbp), %rax
addq %rdx, %rax
movq 8(%rax), %rdx
movq (%rax), %rax
movq %rax, -256(%rbp)
movq %rdx, -248(%rbp)
leaq -240(%rbp), %rax
movq -296(%rbp), %rdi
movq -288(%rbp), %rcx
movq -256(%rbp), %rsi
movq -248(%rbp), %rdx
movq %rdi, %r8
movq %rax, %rdi
call planEmailForSubscriberC
movl -260(%rbp), %eax
cltq
imulq $210, %rax, %rax
leaq emails(%rip), %rdx
movq -240(%rbp), %rcx
movq -232(%rbp), %rbx
movq %rcx, (%rax,%rdx)
movq %rbx, 8(%rax,%rdx)
movq -224(%rbp), %rcx
movq -216(%rbp), %rbx
movq %rcx, 16(%rax,%rdx)
movq %rbx, 24(%rax,%rdx)
movq -208(%rbp), %rcx
movq -200(%rbp), %rbx
movq %rcx, 32(%rax,%rdx)
movq %rbx, 40(%rax,%rdx)
movq -192(%rbp), %rcx
movq -184(%rbp), %rbx
movq %rcx, 48(%rax,%rdx)
movq %rbx, 56(%rax,%rdx)
movq -176(%rbp), %rcx
movq -168(%rbp), %rbx
movq %rcx, 64(%rax,%rdx)
movq %rbx, 72(%rax,%rdx)
movq -160(%rbp), %rcx
movq -152(%rbp), %rbx
movq %rcx, 80(%rax,%rdx)
movq %rbx, 88(%rax,%rdx)
movq -144(%rbp), %rcx
movq -136(%rbp), %rbx
movq %rcx, 96(%rax,%rdx)
movq %rbx, 104(%rax,%rdx)
movq -128(%rbp), %rcx
movq -120(%rbp), %rbx
movq %rcx, 112(%rax,%rdx)
movq %rbx, 120(%rax,%rdx)
movq -112(%rbp), %rcx
movq -104(%rbp), %rbx
movq %rcx, 128(%rax,%rdx)
movq %rbx, 136(%rax,%rdx)
movq -96(%rbp), %rcx
movq -88(%rbp), %rbx
movq %rcx, 144(%rax,%rdx)
movq %rbx, 152(%rax,%rdx)
movq -80(%rbp), %rcx
movq -72(%rbp), %rbx
movq %rcx, 160(%rax,%rdx)
movq %rbx, 168(%rax,%rdx)
movq -64(%rbp), %rcx
movq -56(%rbp), %rbx
movq %rcx, 176(%rax,%rdx)
movq %rbx, 184(%rax,%rdx)
movq -48(%rbp), %rcx
movq -40(%rbp), %rbx
movq %rcx, 192(%rax,%rdx)
movq %rbx, 200(%rax,%rdx)
movzwl -32(%rbp), %ecx
movw %cx, 208(%rax,%rdx)
addl $1, -260(%rbp)
.L33:
movl -260(%rbp), %eax
cmpl $7, %eax
jbe .L34
leaq emails(%rip), %rax
movq -24(%rbp), %rbx
xorq %fs:40, %rbx
je .L36
call __stack_chk_fail@PLT
.L36:
addq $296, %rsp
popq %rbx
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE9:
.size planListOfEmailsC, .-planListOfEmailsC
.section .rodata
.LC17:
.string "(null)"
.text
.globl toJSONC
.type toJSONC, @function
toJSONC:
.LFB10:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $264, %rsp
.cfi_offset 3, -24
movq %rdi, -264(%rbp)
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
movb $0, json(%rip)
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movw $2651, (%rax)
movb $0, 2(%rax)
movl $0, -244(%rbp)
jmp .L38
.L40:
movl -244(%rbp), %eax
cltq
imulq $210, %rax, %rdx
movq -264(%rbp), %rax
addq %rdx, %rax
movq (%rax), %rcx
movq 8(%rax), %rbx
movq %rcx, -240(%rbp)
movq %rbx, -232(%rbp)
movq 16(%rax), %rcx
movq 24(%rax), %rbx
movq %rcx, -224(%rbp)
movq %rbx, -216(%rbp)
movq 32(%rax), %rcx
movq 40(%rax), %rbx
movq %rcx, -208(%rbp)
movq %rbx, -200(%rbp)
movq 48(%rax), %rcx
movq 56(%rax), %rbx
movq %rcx, -192(%rbp)
movq %rbx, -184(%rbp)
movq 64(%rax), %rcx
movq 72(%rax), %rbx
movq %rcx, -176(%rbp)
movq %rbx, -168(%rbp)
movq 80(%rax), %rcx
movq 88(%rax), %rbx
movq %rcx, -160(%rbp)
movq %rbx, -152(%rbp)
movq 96(%rax), %rcx
movq 104(%rax), %rbx
movq %rcx, -144(%rbp)
movq %rbx, -136(%rbp)
movq 112(%rax), %rcx
movq 120(%rax), %rbx
movq %rcx, -128(%rbp)
movq %rbx, -120(%rbp)
movq 128(%rax), %rcx
movq 136(%rax), %rbx
movq %rcx, -112(%rbp)
movq %rbx, -104(%rbp)
movq 144(%rax), %rcx
movq 152(%rax), %rbx
movq %rcx, -96(%rbp)
movq %rbx, -88(%rbp)
movq 160(%rax), %rcx
movq 168(%rax), %rbx
movq %rcx, -80(%rbp)
movq %rbx, -72(%rbp)
movq 176(%rax), %rcx
movq 184(%rax), %rbx
movq %rcx, -64(%rbp)
movq %rbx, -56(%rbp)
movq 192(%rax), %rcx
movq 200(%rax), %rbx
movq %rcx, -48(%rbp)
movq %rbx, -40(%rbp)
movzwl 208(%rax), %eax
movw %ax, -32(%rbp)
leaq -240(%rbp), %rax
addq $30, %rax
leaq .LC17(%rip), %rsi
movq %rax, %rdi
call strcmp@PLT
testl %eax, %eax
je .L39
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movl $8069152, (%rax)
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movabsq $8243313689321545738, %rbx
movq %rbx, (%rax)
movl $975334767, 8(%rax)
movw $8736, 12(%rax)
movb $0, 14(%rax)
leaq -240(%rbp), %rax
movq %rax, %rsi
leaq json(%rip), %rdi
call strcat@PLT
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movabsq $2459000718892870690, %rbx
movq %rbx, (%rax)
movl $975335284, 8(%rax)
movw $8736, 12(%rax)
movb $0, 14(%rax)
leaq -240(%rbp), %rax
addq $30, %rax
movq %rax, %rsi
leaq json(%rip), %rdi
call strcat@PLT
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movabsq $2459000718892870690, %rbx
movabsq $2482718581815670131, %rsi
movq %rbx, (%rax)
movq %rsi, 8(%rax)
movl $2236474, 16(%rax)
leaq -240(%rbp), %rax
addq $60, %rax
movq %rax, %rsi
leaq json(%rip), %rdi
call strcat@PLT
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movabsq $2459000718892870690, %rbx
movabsq $2459029316284215138, %rsi
movq %rbx, (%rax)
movq %rsi, 8(%rax)
movb $0, 16(%rax)
leaq -240(%rbp), %rax
addq $110, %rax
movq %rax, %rsi
leaq json(%rip), %rdi
call strcat@PLT
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movabsq $2863665688611362, %rbx
movq %rbx, (%rax)
.L39:
addl $1, -244(%rbp)
.L38:
movl -244(%rbp), %eax
cmpl $7, %eax
jbe .L40
leaq json(%rip), %rax
movq $-1, %rcx
movq %rax, %rdx
movl $0, %eax
movq %rdx, %rdi
repnz scasb
movq %rcx, %rax
notq %rax
leaq -1(%rax), %rdx
leaq json(%rip), %rax
addq %rdx, %rax
movw $2653, (%rax)
movb $0, 2(%rax)
leaq json(%rip), %rax
movq -24(%rbp), %rsi
xorq %fs:40, %rsi
je .L42
call __stack_chk_fail@PLT
.L42:
addq $264, %rsp
popq %rbx
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE10:
.size toJSONC, .-toJSONC
.globl sendEmailsA
.type sendEmailsA, @function
sendEmailsA:
.LFB11:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movq %rax, %rdi
call puts@PLT
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE11:
.size sendEmailsA, .-sendEmailsA
.globl main
.type main, @function
main:
.LFB12:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $48, %rsp
movl $0, %eax
call initDbA
movl $0, %eax
call fetchSubscribersFromDbA
movq %rax, -48(%rbp)
movl $0, %eax
call fetchCouponsFromDbA
movq %rax, -40(%rbp)
movq -40(%rbp), %rax
movq %rax, %rdi
call selectBestCouponsC
movq %rax, -32(%rbp)
movq -40(%rbp), %rax
movq %rax, %rdi
call selectGoodCouponsC
movq %rax, -24(%rbp)
movq -32(%rbp), %rdx
movq -24(%rbp), %rcx
movq -48(%rbp), %rax
movq %rcx, %rsi
movq %rax, %rdi
call planListOfEmailsC
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
movq %rax, %rdi
call toJSONC
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
movq %rax, %rdi
call sendEmailsA
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE12:
.size main, .-main
.ident "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Mon Dec 21 2020 22:19:41 GMT-0500 (Eastern Standard Time)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: Grokking Simplicity - book by Eric Normand
Description:
Url: http://www.primordion.com/Xholon/gwt/
InternalName: 6424d56a48695ad96175a20ef48394ed
Keywords:
My Notes
--------
December 11, 2020
Eric Normand is writing a book on the basics of functional programming (FP).
It's programming-language agnostic.
All examples use a conservative non-FP version of JavaScript.
He claims that programmers who know JavaScript, Java, C, or C# should be able to readally turn the examples into code in their preferred language.
In this workbook, I describe my efforts to write executable code in traditional JavaScript, JavaScript ES6, JavaScript Ramdajs, C, and Java.
I may also give it a try in Haskell, a new language for me.
Specifically, I will implement the CouponDog application, as described in great detail in chapter 3 of the draft of the book [see ref 1 below].
See my .js and other files in: ~/gwtspace/temp/fp/enormand
http://127.0.0.1:8080/war/Xholon.html?app=Grokking+Simplicity+-+book+by+Eric+Normand&src=lstr&gui=clsc&jslib=ramda.min
MSC
---
title Grokking Simplicity - book by Eric Normand
# To view sequence diagram, paste this text into http://www.websequencediagrams.com/
# Created by: Xholon http://www.primordion.com/Xholon/
# Date: 1608604745133 Mon Dec 21 21:39:05 GMT-500 2020
two_50->three_51: 1010
two_50->three_51: 1011
two_50->three_51: 1012
two_50->three_51: 1013
two_50->three_51: 1014
two_50->three_51: 1015
two_50->three_51: 1016
two_50->three_51: 1017
two_50->three_51: 1018
two_50->three_51: 1019
two_50->three_51: 10110
two_50->three_51: 10111
two_50->three_51: 10112
two_50->three_51: 10113
two_50->three_51: 10114
two_50->three_51: 10115
two_50->three_51: 10116
two_50->three_51: 10117
two_50->three_51: 10118
two_50->three_51: 10119
three_51->four_52: 102john@coldmail.com,2
two_50->three_51: 10120
four_52->five_53: 103john@coldmail.com,2
two_50->three_51: 10121
two_50->three_51: 10122
two_50->three_51: 10123
two_50->three_51: 10124
References
----------
(1) https://livebook.manning.com/book/grokking-simplicity/chapter-3/v-9/
(2) https://gist.github.com/kenwebb/6424d56a48695ad96175a20ef48394ed
this Xholon workbook as a gitub gist
(3) https://www.primordion.com/Xholon/gwt/Xholon.html?app=6424d56a48695ad96175a20ef48394ed&src=gist&gui=clsc
to run the github gist
(4) http://127.0.0.1:8080/war/Xholon.html?app=Grokking+Simplicity+-+book+by+Eric+Normand&src=lstr&gui=clsc
to run this workbook locally
]]></Notes>
<_-.XholonClass>
<PhysicalSystem/>
<CouponDog/>
<One/>
<Two/>
<Three/>
<Four/>
<Five/>
</_-.XholonClass>
<xholonClassDetails>
</xholonClassDetails>
<PhysicalSystem xmlns:xi="http://www.w3.org/2001/XInclude">&gt;
<CouponDog>
<xi:include href="https://gist.githubusercontent.com/kenwebb/6424d56a48695ad96175a20ef48394ed/raw/e9a36271718ffaa86fd5d9e97a0cde4d63deb1c5/CouponDog.es6.js"/>
<xi:include href="https://gist.githubusercontent.com/kenwebb/6424d56a48695ad96175a20ef48394ed/raw/e9a36271718ffaa86fd5d9e97a0cde4d63deb1c5/CouponDog.js"/>
<!--<xi:include href="https://gist.githubusercontent.com/kenwebb/6424d56a48695ad96175a20ef48394ed/raw/62bf8fb3edcace2df7e10def9c9f6fdea9481ac1/CouponDog.ramda.js"/>-->
<One>
<Two/>
<Three/>
<Four/>
<Five/>
</One>
<InteractionsViewer/>
</CouponDog>
</PhysicalSystem>
<Twobehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, beh = {
postConfigure: function() {
me = this.cnode.parent();
//me.println(me.name());
//me.next().msg(101, $wnd.xh.param("TimeStep"));
//me.next().msg(102, );
},
act: function() {
//me.println(me.name());
me.next().msg(101, $wnd.xh.param("TimeStep"), me);
}
}
//# sourceURL=Twobehavior.js
]]></Twobehavior>
<Threebehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
const subscribersRawD =
`john@coldmail.com,2
sam@pmail.co,16
linda1989@oal.com,1
jan1940@ahoy.com,0
mrbig@pmail.co,25
lol@lol.lol,0`
var me, line, beh = {
postConfigure: function() {
me = this.cnode.parent();
//me.println(me.name());
line = "";
},
act: function() {
//me.println(me.name());
},
processReceivedMessage: function(msg) {
//me.println("msg: " + msg.signal + " " + msg.data + " " + Number(msg.data) + " " + typeof msg.data);
if (msg.data) {
var chr = subscribersRawD.charAt(Number(msg.data));
if (chr == "\n") {
me.next().msg(102, line, me);
line = "";
}
else {
line += chr;
me.println(line);
}
}
}
}
//# sourceURL=Threebehavior.js
]]></Threebehavior>
<Fourbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, beh = {
postConfigure: function() {
me = this.cnode.parent();
},
processReceivedMessage: function(msg) {
me.println("Four: " + msg.data);
me.next().msg(103, msg.data.split(","), me);
}
}
//# sourceURL=Fourbehavior.js
]]></Fourbehavior>
<Fivebehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, beh = {
postConfigure: function() {
me = this.cnode.parent();
},
processReceivedMessage: function(msg) {
me.println("Five: " + msg.data[0] + " " + msg.data[1]);
}
}
//# sourceURL=Fivebehavior.js
]]></Fivebehavior>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg">
<g>
<title>CouponDog</title>
<rect id="PhysicalSystem/CouponDog" fill="#98FB98" height="50" width="50" x="25" y="0"/>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment