- Hung out with Eric and the whole family all day. Woke up at 6, gymmed, then beached and piered.
- Created the splitwise group to settle all the Austin finances.
- (Certain) Corporate action(s) can be taken without a shareholder meeting, even if the company is private, like SpaceX. It must win by majority shareholder vote nonetheless. They must notify the shareholders, by law.
- These are usually equity dilutions, like increasing the total number of shares by ~0.01%.
- This directly decreases the percentage of the company you own, and therefore your voting right, but that was never substantial anyway. It does affect value though, because external valuations are usually done on the total worth of the company, and then simply divided by the number of shares. It's a sneaky, indirect way to dilute your equity, since these events (dilution and valuation) are usually months apart.
- Did Hawaii planning.
- The friends leg is just pettys/gmereks/remilins (6) so far.
- Harner/Eddie/Jonny already have flights home and other plans.
- Allie is out for the friends leg, and is waffling the wedding leg.
- Wes/Jcriss/I are the other 3 who are considering the friends leg, which would make 9. If so, Wes and I would be the only ones with the same flights for the whole trip.
- I would like to go both legs. I will definitely need the LAX-HNL flight for the wedding. If Wes and Jcriss go on the other leg, I'll definitely go, and would need HNL-LIH + LIH-LAX. I would like to encourage Allie to come to both.
- I can make al pastor for the bay whenever they come down.
- Trim a pork butt into strips (easier to buy boneless for this, obv).
- Make my usual dry rub (salt, pepper, paprika, garlic, onion), but then add Achiote paste and Guajillo chili powder and mix it all with pineapple juice to make a marinade (or just buy a premade pastor marinade). Let it sit overnight, then smoke as usual.
- Spritz with pineapple juice instead of water.
- Using openssl you can create a root certificate (used to generate other certificates) and then specify localhost as the domain to trust. Fairly simply article here: https://medium.com/free-code-camp/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec.
- Guajillo chiles are the second most popular chile in Mexico. Poblanos are #1. Ancho is the name for dried Poblano.
- The carolina reaper is the hottest pepper in the world. Before that it was scorpion, then naga, then ghost. There are claims for 2x the carolina (Pepper X) but they have not been confirmed yet.
- New peppers are created by literally breeding other insanely hot peppers.
Tuesday, June 18, 2019
Monday, June 17, 2019
- Remember superchargers and turbochargers are a little different. Both compress the air going into the engine to add about 50% more power, but the turbo takes it from the exhaust gases (turbine->compressor) and the super takes it from the crankshaft (belt->compressor). The turbine has a slight amount of lag and then will lurch forward (because the air must move through the whole engine before you get the boost). The super delivers extra power all the way through. The Kawasaki Ninja H2 is the first bike with a super, I believe. There are custom Hayabusas with turbos.
- Oh, forgot to write my Franklin's BBQ review.
- Rankings:
- Brisket. The best I've ever had.
- Ribs. Good, but too much pepper.
- Pulled Pork. The usual.
- Turkey. Tasty, but too much butter, and they only had breast.
- Sausage. Surprisingly bad.
- Overall, the brisket was incredible. Everything else was about par with what I cook at home.
- The wait in line / drinking / relaxing was fun. We went on a Thursday and waited from about 830-1230. Worth it to do once - is probably not worth a repeat when there are so many other comparable BBQ places around.
Sunday, June 16, 2019
- Back home from the Austin trip with Richard and Derek! Was a blast. We even go to talk to James.
- Medieval Times for Eddie/Ray/Haley yesterday. Awesome place.
- USWNT beat Chile 3-0.
- Finished Leadership and Self Deception and The Untethered Soul. Added notes to drive.
- Periodicals:
- There's a <clippy> html element now: https://shkspr.mobi/blog/2019/06/introducing-the-new-html-element-welcome.
- The most-spoken languages in India: Hindi 57%, English 10%, Bengali 9%. Punjabi is only 4%. https://en.wikipedia.org/wiki/Multilingualism_in_India.
- You can use nacho analytics (and google analytics) to see the traffic on any website, not just your own. https://www.nachoanalytics.com/. I started reading this, thinking it was going to reveal a cool website trick for growth/etc, but it ended up just being a sales pitch for nacho's feature set: https://www.nachoanalytics.com/blog/amazons-growth-hack/.
- Did some research for the Hawaii trip, both the first wedding leg and the second friends leg. Tentatively:
- Fly from LAX to Oahu on Thursday August 8. Wedding Saturday 10th.
- Leave Oahu Tuesday August 13 for Kauai. Stay at the Sheraton Kauai resort.
- Leave Kauai on Saturday the 17th.
Tuesday, June 11, 2019
- Really tough yesterday with Kevin Durant.
- Reinjured the same leg, likely from playing before being ready/healed. You can see the leg snap here: https://youtu.be/lYrA30qcvK4?t=49.
- Bob Myers gave an emotional statement about it: https://www.youtube.com/watch?v=K3esK_em420.
- Awesome reunion of 88 year old dad with 53 year old son with down's: https://www.youtube.com/watch?v=XXDvD-jLn74.
- Cancelled classpass.
- Received and set up the wireless mouse. Works great. The usb a-c adapters work well too.
- Woah. You can send documents to your kindle via email. This is very convenient right now since my ubuntu laptop can't talk to it. You simply make sure your email is whitelisted (your default amazon address is), then email your kindle address (check in device management, like brian.mahlstedt_<number>@kindle.com). You can type "Convert" in the subject to automatically convert. Amazing. Did this for two documents.
- React/redux work. Took notes on my google doc.
- Played with youtube live again. You have access to the same settings beforehand: private, public, chat enabled, etc. You can then edit the video after you end the stream, but it's only stuff like captions and other standard settings. You can't snip, filter, add sound, all the advanced editing functionality. Do that offline and upload, don't use livestream.
- The women's world cup started. United states beat Thailand 13-0!
Monday, June 10, 2019
- Android emulation.
- Genymotion is probably the most popular android emulator for linux. Downloaded the personal-use edition.
- Needed to apt install virtualbox first. Then chmod +x the genymotion bin and simply run it.
- Created a desktop icon for it so I wouldn't have to execute the binary from the command line every time (and leave the pesky terminal around). Just create a APPNAME.desktop file with a hashbang that farms out to xdg-open, including the paths to the binary and the icon.
- Added StartupWMClass to the .desktop so the icon wouldn't duplicate.
- When emulating a device, my laptop craaawled. The galaxy s9 was unusable. An old Google Pixel (around galaxy s6 days) was even slow. My laptop only has 3.6GB of ram and 8GB of swap, but all ram was railed and swap was at 50%. Not sustainable, and I hadn't even run any heavy android apps yet.
- Ended up unistalling genymotion and virtualbox. Was too slow.
- Looked around and found Anbox, which runs Android in a container instead of a vm, and farms many android tasks back to your native linux host.
- Added the ppa and installed linux-headers-generic anbox-modules-dkms. Then installed the anbox snap.
- Google play store doesn't come automatically with android (licensing and such). You'd normally have to install apks manually, OR the better option of something like houdini. This script provisions all of that for you: https://github.com/geeks-r-us/anbox-playstore-installer/blob/master/install-playstore.sh.
- Anbox also didn't work. Games wouldn't open because of Anbox' unique configuration.
- Lastly, looked at the Android SDK itself. It requires minimum 4GB ram and recommends 8GM. Mine is below both.
- In summary, my laptop does not have enough memory to use a VM-based android emulator.
- Bought an adapter to connect my phone/laptop to older hard drives and kindle and such. Usb-c (android size) male to usb-a female.
- Remember, usb-b is the boxier one (usually printers and such).
- Micro and mini are the other obvious ones.
- Also, remember, usb-c comes in two sizes: android and iphone. My linux laptop is the android size, because that's the standard. If you see usb-c with no other qualifiers, it's the android size.
- Bought a wireless mouse as well.
- Reinstalled the gnome system monitor. It doesn't open sometimes, and this seems to fix it.
- MD. In javascript, the variable declarations are hoisted but not their values.
- I feel like an absolute idiot for never taking advantage of this, but you can actually do curly brace expansion in bash. `echo {hello,world}` or `echo {0..10}`. You can even combine two curly brace arguments for combinations. My goodness.
- DKMS = dynamic kernel module support. Used with virtualbox.
- Shopped for a RAM upgrade to my XPS13.
- DDR4 is newer and faster than DDR3L, which was a midterm upgrade for DDR3.
- Need a T5 to open the back.
- Unfortunately, I can't upgrade the RAM on the 13 easily because it's solder to the motherboard lol. On the 15" and above models, they have additional slots but the 13" does not. In order to have more RAM, I would have needed to upgrade at factory purchase, or replace the whole motherboard myself.
- Don't need the torx screwdriver anymore.
- Brainstormed some ideas for internet companies. Nothing huge jumped out, but the immersion helps. I want to be more mindful as I go through my day-to-day about anything that is annoying, even in the slightest. These inconveniences are just opportunities for improvement.
- YouTube.
- Went through my channel and removed liked videos. Added a few subscribers.
- YouTube Studio is in beta. It's a cool dashboard for everything on your channel.
- You can see your total subscriber count, but not the individual subscribers (unless they've chosen to allow that to be public).
- You can change 3 privacy settings: your liked videos, your subscriptions, and your playlists. All of mine are not public.
- You can livestream, but YouTube is much more geared toward recording and editing a video offline, then uploading it.
- Motorcycles
- Cool drag race: https://www.youtube.com/watch?v=DnTL4wDAbK0.
- Quarter mile ranks:
- H2R
- F1 Redbull
- F16
- Tesla P100D
- Aston Martin Vantage
- Plane
- Lotus Evora
- Observations:
- Off the line, the bike and F1 and Tesla were all about the same, dusting everything else.
- The bike took the lead through the midrange.
- At a quarter mile, the bike and F1 were about the same, ahead of everything.
- After that the F1 would have overtaken the bike.
- After that, the aircraft pull way ahead.
- H2R facts:
- Same combustion volume as my ducati, but over 4 cylinders instead of 2. About 2x the horsepower and 1.5x the torque. About 35lbs heavier also.
- It's currently the fastest motorcycle. It's not street legal.
- It can go from 0-250mph in 26s (lol): https://www.youtube.
com/watch?v=6_n7ru1e-rg. My ducati top speed is probably around 170mph, and would get there in around 15s. - Gave Ken about 5lbs pulled pork for home, and gave Allie about 5 more pounds to bring to work. I'm leaving for Texas so I won't be able to finish all the leftovers before Wed.
- Finals game 5 in toronto. Warriors won! Back to Oracle.
Sunday, June 9, 2019
- Got over 3500 pages of printed documentation from healthnet in the mail, unsolicited. It's basically a printout of a registry of all provider. This is unacceptable in 2019. It's a gigantic waste of paper, shipping infrastructure, delivery jobs, and more. Sure, there might be a percent of members who do not have access to a computer, but this paper delivery should be opt-in during member registration.
- Paid a $48 parking ticket on Allie's car because we're in the summer 1hr months.
- Great day of volleyball. Tweaked my back a little bit.
- Bruins push to game 7.
Saturday, June 8, 2019
- Parents left. Was a great couple days. Cooked leftover smoked chicken stir fry on thursday, sweet potato homefries and bacon and poached eggs and bananas/blueberries on friday morning, then smoked pork shoulder on friday night.
- Warriors lost last night, didn't look good.
- Interesting video on some pitfalls of streaming services like netflix: https://www.youtube.com/watch?v=fDF-S68kx5o. It's not healthy competition. Every show is IP which means it has an exclusive license. Like a ... monopoly.
- saidit.net looks like it was closed.
- Finished Harper's Island. Was pretty decent.
- UFC 238. Shevchenko had the best female KO I've ever seen. Cejudo was a monster as well.
Wednesday, June 5, 2019
- Bought the flight to Austin, Wed-Sat (have to be back before Eddie's). It's a little early on Sat morning (7am), which will suck after Friday night, but it was the best option. Used 25k miles, leaving the price at $6. I have ~150k miles left still. Probably do Franklin on Thursday, get in line at 8am and drink chair beers for 3 hours until they open.
- Meta = most effective tactics available. Used in gaming, refers to the best strategy/combo.
- Talked to pops. They're gonna come to hermosa tomorrow and we'll have a couple days to hang. Shopped to make sure I had enough for them.
- Warriors game 3.
- Klay, Durant, and Looney all out due to injury.
- Iggy, Boogie not 100%.
- Steph and Draymond the only starters who are normal. Wow.
Tuesday, June 4, 2019
- Idiosyncrasy = odd habit, peculiarity. If someone is idiosyncratic, they're peculiar.
- Netflix Tech Blog: container cpu isolation.
- CFS = Completely Fair Scheduler. Mainstream solution to timeslice the cpus properly.
- They wrote another better one call titus-isolate, optimized for their container usage.
- Kawhi filed a lawsuit yesterday against Nike for using the logo he designed:
- Bought a yoga mat finally so I don't have to keep borrowing from friends (or paying $2 rental) for each classpass.
- Aprilia's mainstay, the RSV4, comes in a few models.
- RR and RF are basically the same but the RF has a little better suspension and tires.
- LE means limited edition. Usually just graphics / aesthetics.
- FW means factory works. This is their GP bike, the best race bike.
- Derek reached out about visiting Dick in Austin. Looked at flights next wed-sat (would have to be back for eddie's renn faire lol) and they were $190.
- 20 year prediction: 10% of all jobs will become remote. Offices and commutes will become inefficiencies of the past.
- Dcraig hit me up about the signed goodbye poster they forgot lol. Told him that Allie or Spencer could take it home, but otherwise I'd be happy to catch up as well!
- Smoked chicken. Added to journal.
- Fed mouse.
- Grandma passed away tonight. So thankful for the complementary model she and grandpa left for us, and maybe even moreso for the model they raised their own children with - my mom/dad + aunts/uncles sure paid it forward. As I was hanging up with my mom, trying to plan a time to meet, the words "we'll stay in touch, and we'll find a way" came out of my mouth. I don't think that was an accident.
Monday, June 3, 2019
- How many movies/shows would even remain if you removed the "pinned girl hits mounted attacker with unnoticed sharp/heavy object" scene ... ?
- Costco, reupped on chicken and almonds.
- Average salary for a pharmacist is ~125k in our area.
- Education.
- You can't declare bankruptcy on student loans.
- College is 2.5x more expensive than it was a few decades ago. Most of the bloat is due to administration.
- Now, in 2019, more information can be found online than in universities. In many cases, the quality is better as well. Individuals can give themselves the capabilities which merit a degree, but there's no accreditation mechanism yet. A business that found a way to do this (likely a well-designed sequence of tests) would uproot all of academia (for the better!). Loans, inflation, tribalism, administration, federal funding - so many improvements.
- If you have a memory that's a couple years old, and you still have an emotional reaction to it, you need to address it! What was the cause? What could you have done better? How can you improve yourself to improve that outcome next time? This introspection is huge. If you're plagued by your past, your body produces the stress hormone cortisol, because it's an alarm to a vulnerability. Cortisol makes you age! Once you isolate the cause and understand how to better act next time, your body literally becomes healthier.
- Notes from pharmarket meeting yesterday:
- Info:
- We'll have an account soon to compare.
- Certain drugs have way better ROI. Go after those vendors first.
- Hold the money for a month until vendor billing cycle, then collect X percentage from vendor. Show original prices on our site.
- Offer service to feed prices, for the vendors without a frontend. They can update a google sheet or something and we can fetch it. This is a huge benefit for smaller vendors who want their stuff in the marketplace.
- Universal app wasn't as complicated as we had thought, just basically need a license.
- Meds have way more regulation, that's why amazon integration is hard.
- Ezrirx and amazon are both in this market, but that doesn't mean we can't take a stab.
- Medline is another company that sells (non-rx) supplies.
- There is so much value in aggregating the search locations alone. Instead of buying 6 supplies from 4 separate sites, do it all in the same place.
- https://www.mdm.com/2017-top-pharmaceuticals-distributors
- 3 companies account for more than 90% of the drug distribution market: AmerisourceBergen (ABC), Cardinal Health (CAH), and McKesson (MCK). These are the "Big Three Wholesalers" and each has a revenue of well over 100B alone (together almost half a trillion).
- Amazon's revenue in 2018 for comparison: 230b.
- The next few large wholesalers: CuraScript, Morris & Dickson, Smith, FFF, Rochester, North Caroline Mutual, Anda.
- Action items:
- Finish the MVP website.
- Get domain name and host.
- Populate with fake data from multiple vendors. You might be able to get some public data for generics. Some sites even list their rx (like https://auromedics.com/products/ampicillin-and-sulbactam/, for example).
- Write template API that we'll encourage vendors to use.
- Add basic user login which protects the price comp tool endpoint.
- Add basic landing page which shows the benefits for (a) pharmacies and (b) vendors (separate tabs?).
- Go speak with vendors. Get them onboard and get their data. Then go speak with pharmacies. Get them to use it. Then repeat and grow.
- Here is where you can search for some vendors: https://search.dca.ca.gov/.
- Parlays. They're simply a compound bet. Instead of betting for a single team to win (or a single line, or whatever), you're betting for multiple. As long as none of them lose, you win. Because of the compound probability of failure, the payouts are usually very high
- Adding team parlay bets to the supercontest app would be huge. People would love it. Look at how popular fan duel is for players. Opening these bets up to teams would be a great opportunity. Created https://github.com/brianmahlstedt/supercontest/issues/49.
- James lost on jeopardy! He was 60k from beating Ken's alltime record, and his average was 80k per night, so tonight should have been the night he became the GOAT. The opponent got both daily doubles, which was an inevitable misfortune eventually, but I still find it so strange that everything happened to fall into place tonight. After 32 victories, his streak ends on literally the night it should have become the record. Hm.
Sunday, June 2, 2019
- Watched Ma yesterday. Loved it! Was a fresh premise for the horror genre so overloaded with repeats.
- Stanley cup game 3 and UFC Gus vs Anthony Smith yesterday. Streams are now posted on https://saidit.net/s/MMAStreams/comments/ because r/mmastreams was shut down.
- D3 = Data Driven Documents. It's a way to manipulate the DOM as data changes.
- https://www.ibj.com/articles/72632-amazons-latest-target-is-pharmacy-disruption
- Indiana has a ton of fulfillment centers that deliver meds.
- They've been working on entering this market since ~2017.
- This will help drive prices down, obviously, as it has done for all other open markets on amazon.
- Amazon bought PillPack (online pharmacy) for $753m.
- CVS, Walgreens, and RiteAid lost over 11b in market value that day.
- Art said this won't affect independent pharmacies, just the big chains.
- Amazon wouldn't need to create an infrastructure to compare prices, it's already baked into their stack. Filters, sorts, etc. Our kayak-like pharmacy wouldn't be of much value.
- Met with Art again. Will post notes tomorrow.
- Warriors game 2!
Friday, May 31, 2019
- HN.
- Awesome people map: https://pudding.cool/2019/05/people-map/.
- EOLs for common products: https://endoflife.date/.
- Jordan Peterson and Ben Shapiro: https://www.youtube.com/watch?v=1opHWsHr798.
- Something like "inheritance jealousy" - if a dumb person inherits a billion dollars, you might be mildly annoyed because of their luck. If a competent, smart person gets a billion dollars, you are much more jealous. You are more threatened. Hierarchies are fundamentally efficient structures, and they provide purpose + goals, but they create resentment in the majority. Cain and Abel.
- Audited all the phone bills and sent the balance (looks like $240) to mom to confirm.
- While there are babel libraries to offer multi-language support, in webdev babel is the javascript compiler.
- Split was Hollywood's first surprise sequel, where it was not marketed as such and rather left the bruce willis surprise for the end of the film. It follows Unbreakable, and the trilogy is concluded with Glass.
- I like the whitestrips more than the mouthpiece with the light. It's too salivating. However, I do like the sequence of charcoal brushing right before the treatment, and will do so for whitestrips in the future.
- React and redux practice.
Thursday, May 30, 2019
- Most had originally thought (amount in diet = amount in blood). So, if you ate more cholesterol, for example, your blood would have more cholesterol, which is bad. Now, the equation is more clearly (amount in diet + amount produced = amount in blood). This applies to a lot, and is changing how we view a lot of foods (especially ones that were historically looked down on like saturate fat). If you eat more of something, your body produces less of it, and vice versa.
- Transferred 10k (online limit) to parents, then went in to transfer the other 20. Spoke with a customer service representative about the $5 fees on the closed savings account. They said that they can revert fees up to 90 days old, so they credited $15 dollars back to my account lol. The other 200+ are lost.
- Interesting PEP for the removal of many stdlib modules, due to obsoletion and/or replacement: https://www.python.org/dev/peps/pep-0594/#deprecated-modules.
- RSVPed for 2 for Arlen/Rob's wedding. Eddie is gonna add us to his AirBnB. I'm gonna wait to buy flights because I don't know if I'll be leaving from the Bay or LA.
- With some elimination, I've noticed a pretty clear causation for my back pain. It's Leg Day. I need to be extremely cautious, warm up, and stretch before any of these lifts.
- Homemade sushi for the first time ever, it was amazing! Sticky rice, spicy sesame oil, salt and pepper, seaweed, salmon, avocado. That's it. Cost about $16 for 4 rolls, probably half the restaurant price.
- WARRIORS RAPTORS game 1 finals.
- Talked with Art a bit more.
- Because we decide to flee or pursue, we should speak with pharmacies. User storymapping. Discuss the problem before understanding the solution.
- A footrace is gonna have execution risk. Other products are way ahead, with bigger staff, etc. If we try to make a cleaner website, an easier signup process, a larger pharmacy base, rebates whatever - then we're probably going to lose. We need to shift a bit more into market risk. What different feature does our stack have that others don't? What additional service can ours provide?
- Other models: buy in situ (orbitz model), take a percentage cut (amazon).
- Another model we could try: redirect for purchase and take a query fee (kayak).
Wednesday, May 29, 2019
- Teeth whiteners. Newer charcoal products are effective at removing stains, because activated charcoal's outer pores will strip away any foreign bodies on the outer surface of your teeth. However, they don't bleach the teeth like hydrogen (or carbamide) peroxide based whiteners do. These take time, working beneath the surface to actually change the color of your teeth. I'll probably get a charcoal jar to use sparingly (maybe brush once every couple weeks) for regular maintenance, but still use whitestrips about once a year for the actual whitening effect.
- Went to store, placed regular amazon order, and amazon fresh order! All for various elements of making sushi at home tomorrow.
- There are MANY important KPIs for websites: dwell time, new unique visitors, signups, return visitors, on and on and on. https://databox.com/website-kpis-and-measuring-performance.
- Watched an entrepreneurship video from FW: https://www.youtube.com/watch?v=Q-Cbav_Dt2s.
- Market risk. Better to play this game as a young person with an idea. Usually something novel, first product/service to create the market. You're buying a lottery ticket. Higher risk, higher reward.
- Execution risk. Better to play this game as an established entrepreneur. Usually not a market-changing technology, but some improvement that's basically guaranteed to become successful. You can buy a team of sales, marketers, employees etc to see it to market first. Lower risk, lower reward.
- This guy is pretty cool. Justin Kan. Biggest creation: twitch. He has a few smaller ones as well. He talks about mindfulness and how important diet/sleep/exercise/meditation are to his success.
- Company culture is so so important. Make your employees feel like things are happening through them instead of to them.
- Started reading two books: The Untethered Soul and Leadership and Self Deception.
- Jon Snow checked into rehab: https://www.usmagazine.com/celebrity-news/news/kit-harington-checked-into-treatment-center-for-wife-rose-leslie/.
- Went to bank of america. Deposited my solium check. Can't transfer until it clears (SOB tomorrow). Transferred my remaining balance in the savings account to the checking account, then closed savings. The $5 monthly fees were for being below a minimum lol. Ridiculous policy. The agent said she would try to waive them.
- Did some valuation research on the ninja. KBB, cycletrader, and craigslist all were in the range of 2-3k for my year, odo, condition, etc. I would probably sell to a private party at around 1.5k because of the shift fork on 2nd gear. I might drop as low as $1000 for a friend.
Tuesday, May 28, 2019
- Finally got a tracking number for Urthbox. If it arrives in a couple days, it will have taken 2 months to arrive after the order was placed.
- The Solium check hasn't arrived either. If it arrives tomorrow, it will have taken 2 weeks for a $20 delivery fee.
- Cheerio is the npm package for using jquery in node. You can select DOM elements, act on them, etc. Also serves a functionality like beautiful soup.
- Axios is the npm package for an http browser client, like solium. It enables webscraping.
- The chase for the world's largest tesla coil: http://lod.org/. Lightning on demand!
- Pharm
- Startup research.
- Develop your business model.
- Plan to grow, services provided, etc.
- Build the beta website.
- Develop your company model.
- Create the LLC.
- The contracts between cofounders of a startup are pretty well figured out at this point: https://fi.co/insight/how-to-create-the-perfect-cofounder-agreement-with-your-business-partner.
- Vesting schedule. Founder's equity. The person who had the original idea should increase by about 5%. If no other employees/investors have equity, this would mean 55/45.
- Patent/Copyright/Trademark/Trade Secret. Usually one is necessary.
- Get funding. NDAs are necessary here.
- Market to customers. Expand.
- LLC research.
- Limited Liability Company. The owners won't risk personal assets if it goes bankrupt or gets sued. Can't intermix personal money.
- To start an LLC, you file Articles of Organization and Operating Agreement with the Secretary of State (online) and pay a fee.
- LLCs can choose to be taxed like a partnership (see LLP below, basically personal income tax for partners) or like a corporation.
- Different from:
- Sole proprietorship. The simplest. The owner is responsible for all debts. It is not a legal entity. Just register for license. Also allows you to mix personal funds with the business. Taxed with owner as regular income.
- Partnership. Can be general partnership (like sole proprietorship but with an even split for profit/debt across multiple people) or limited liability partnership (called an LLP, and still taxed on the partners' personal taxes). LLPs are common for architecture and law firms.
- Corporation. The most common for larger companies. You have to have common stock, license, board of directors, etc. Very similar to LLC, just larger. The owners still have limited liability. The corp is basically another person in legal eyes. They're taxed separately and make decisions separately. Corp vs Inc - it doesn't matter, but once you declare, you have to be consistent in all your legal nomenclature after that. Most common type is C Corp.
- Allie knows a decent amount about all of this.
- Looked up some more domain names. These are available: focuseuticals, rxcenterpiece, keynoterx, plazapharm, rxcapitol, bazaarpharma, bazaarpharm, racketpharm, pharmracket, pharmaracket, rxracket, rxcrux, kernelpharm, pharmakernel, kernelrx, rxkernel.
- I loooove racketpharm because it sounds like "rocket farm" and implies you're getting something for ridiculously cheap, but has negative connotations because technically rackets are illegal business handlings so it might deter people.
- kernelrx and bazaarpharma both sound pretty good too, and are self-descriptive.
- Still a little hesitant due to the maturity of other established sites.
Sunday, May 26, 2019
- Murder mystery party was awesome yesterday. The curry brisket turned out pretty good as well. We finished one packer and I took the second home for leftovers this week.
- Cast iron pans shouldn't be soaked, for fear of rust. They also shouldn't be washed with soap, which might strip some of the seasoning on the pan (the seasoning is usually vegetable oil).
- Warriors raptors finals baby. We're the heavy favorites, but I love both teams. Some articles some that this is a bigger threat than Lebron's Cavaliers the best 4 years. That's ridiculous. There have been 9 NBA finals sweeps in the history of the league. I wouldn't be surprised if this becomes the 10th. Also, Drake is a diehard raptors fan but has warriors tattoos.
- Reminder about betting lines. If a team is +150 and you bet $100, you would get back your $100 plus $150 in winnings. If a team is -250 and you bet $250, you would get back your $250 plus $100 in winnings. A positive line is for the underdog and you risk less than you gain. A negative line is for the favorite and you risk more than you gain.
- The superbook line is -310 for the warriors in the finals, a very heavy favorite.
Friday, May 24, 2019
- Scrolldown animations are very popular now. Just slight shifting of the text and increasing opacity is enough to give the user a nice scroll feel. Also gives a bit better load time and responsiveness, since the lower panes don't have to load when the initial page does.
- Decent overview: https://www.bluecompass.com/blog/how-to-liven-up-your-website-with-scroll-animation.
- The difference between iterator and iterable. They're very similar, they just slightly differ in how Python deals with them under the hood. Both can be looped over. Iterators just have an explicit __next__() method so they inherently know how they're supposed to be iterated over. Iterables don't have this behavior. Python calls iter() on them to determine how to sequence the iteration. TLDR: An iterator has the "how to iterate over my data" baked into it. An iterable does not.
- Put the new amex credit card info for AAA autopay.
- HN
- FB makes it very hard to get your data off. Some have written tools to help: https://github.com/weskerfoot/DeleteFB.
- https://www.starlink.com/
- vars() is useful. Called without arguments, it's like locals. Called on a variable (like vars(myvar)), it will return the __dict__ elements.
- Cool visual about how website design has changed from 1990 till now: http://fabianburghardt.de/webolution/.
- Wonderful collection of bash reminders: https://github.com/jlevy/the-art-of-command-line.
- Meditated for a bit today for the first time in a long time, love it. Great for destressing.
- Did a little research into carnivory and other dietary choices. Some are extreme, like the sole "beef-salt-water" lifestyle. There are worshippers of this end of the spectrum, just like there are on the vegan side. Both with firsthand accounts and both with scientific research. Cholesterol too. Diff btw dietary cholesterol and blood cholesterol.
Thursday, May 23, 2019
- Yesterday spent the day in San Bernardino again.
- Notes from art meeting Tuesday:
- Prices drop after the usual patent (10yr?) expires, allowing generic meds to flood.
- AWP = average wholesale price. There are usually hot items that have low awp and high resell value. Knowing these waves is much easier if you work in the industry.
- Redirects and utm query params can identify the majority of traffic induced by our hub. Probably not close to 100%, but maybe ~70%?
- LOTS of domain names are taken.
- Can have public accounts for otc and pharmacy accounts for rx.
- Applications take a few days and require signatures, etc. Some are even still mail, not digital. Abstracting all of this into a universal application has value on its own, even without the price comparisons. We'd aim to do both.
- Getting a read-only account is another option. This seems more core to the principles of the idea. Completely skip all buying capability, just show prices. No account, nothing. Simpler.
- Befriending a vendor would be huge at this stage. Could give details on price margins, traffic amounts, value of our product, etc.
- Identity Politics. It's something I've always been familiar with, but never knew the formal name for. Individual identity should come before group identity. Tribalism has historically ended in violence, and our modern world continues to confirm this. So much political conflict twirled around race, gender, etc.
- PW/MD.
- Checked mail. The solium check which was shipped on May 15, eight days ago, with a delivery method that cost $20, has not arrived yet :)
- Bought brisket from costco. Trimmed and brined. Also bought jelly bellies for the counting game.
- Bought prizes (drinks) from vons, as well as ring toss bottles (perrier lime lol).
- Wow, this pharmarket alternative already exists: https://www.ezrirx.com/
- Based in New Jersey. Founded 2016. They have the universal application, price comparison, and in-situ purchasing :/
- We'll create an account to see the list of wholesalers. If it's not that many vendors, the market is still open.
- Even if it's legit, we have another model that may work: no account, no buying power. Just show up to the site and compare prices, like kayak. The hard part about this is it involves uprooting the status quo. We'd basically have to convince vendors to publish their prices.
- In order to fully immerse someone in an experience, you must attend to as many senses as possible. Think of a date: a scene with candles, chocolate, music, flowers, and physical touch is much more impressive than an alternative with any one sense missing.
Tuesday, May 21, 2019
- Sent out all murder mystery invitations, as well as the printouts and office supplies and decorations. This is a lot of work!
- India's Tandoori up near Allie in miracle mile has a lunch buffet that goes until 3. I went today, so good.
- GRRM blogpost after the series finale: http://georgerrmartin.com/notablog/2019/05/20/an-ending/.
- The expedia/priceline business model:
- The customers are not the individual users. The customers are the companies selling through your marketplace.
- The cofounder of Kayak was the cofounder of Orbitz before. The key change which made Kayak successful was that it no longer sold tickets, it just became a search engine to aggregate prices and compare. This was easier to maintain, fewer employees, no customer service needed, etc.
- Kayak gets about half its revenue from referrals (flight/hotel/car companies paying them) and half from advertising.
- Kayak earns anywhere from 0.1 - 0.3 cents per query for flights, cars, and hotels (hotels being higher).
- Amazon takes anywhere from 6-20% cut per item sale (average 15%), as well as monthly dues to even list items ($0-$40). There's also a minimum (a dollar or two) in case 15% of an item sale is less than that.
- Progress:
- Free for pharmacies. Money comes from vendors. Could take a percentage of sales or charge a fee per query. We'll have to iterate on the sweet spot for this number until it makes sense for both parties.
- Roadmap:
- Add a few more vendors.
- Enable user accounts, necessary to store partnership information and vendor credentials and such.
- MVP is done. Show it to pharmacies. Get them to use it.
- Once there are enough users, start pitching to vendors (our actual customers).
- In production, we should not aggregate prices by webscraping. Supported vendors should expose a contracted API for our data.
- Possibly: buy bulk and resell for discounted rates, just like kayak does with hotel blocks. To do this, we'd need to add functionality/complexity to the app. It would allow buy/sell instead of just redirect.
- Start trending history and offering price prediction.
Monday, May 20, 2019
- HN/PW.
- Papermill is a tool that takes a Jupyter notebook (and some params) and executions it with a production context in mind (saving artifacts, etc). Netflix has been pushing these architectures hard, even outside of the data science workflows at the company, because it's a great way to combine runtime with notes/datasharing for others to consume.
- Some awesome gems in python 3: https://datawhatnow.com/things-you-are-probably-not-using-in-python-3-but-should
- fstrings for autoformatting based on variable names.
- built-in lru.
- type hints.
- no __init__ necessary for subpackages.
- Game of thrones and barry are done, mostly just nba/nhl now (although that will finish soon too). Westworld s3 trailer came out (parts filmed right here in hermosa).
- Very interesting segment! https://www.youtube.com/watch?v=aMcjxSThD54.
- Warriors swept Portland, off to the 5th consecutive finals!
- Bought the circus murder mystery night (from a new company), started preparing everything for saturday.
Thursday, May 16, 2019
- PW and MD.
- Cool comparison between Vue and React: https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-e9a1ae8077fd.
- Sharks won last night in overtime with a hand-pass assist (lol). Wasn't caught live so it wasn't reviewable. Warriors tonight.
- They moved us up from B to A league softball playoffs last night (although we'd rather have stayed). Lost by a lot.
- Looks like bmanning started a new space company in Palo Alto? https://www.linkedin.com/company/xona-space-systems/.
Tuesday, May 14, 2019
- Back from LiB! Great trip. Uploaded and shared pictures.
- Yesterday caught up on all the quarterfinals NBA/NHL games that I missed, game of thrones, and ufc/bellator events.
- QR stands for Quick Response in QR codes. The most recent version is a 177x177 grid.
- Emails, newletters, HN, PW, MD, etc:
- Guido about creating python (as a middleground between C programs and shell scripts) and stepping down as BDFL: https://www.youtube.com/watch?v=qxMcGDnT8uc.
- SQL is old and has many pitfalls. We should not resist the forthcoming of newer query languages.
- Some good response headers to add to your server's HTML pages:
- Strict-Transport-Security: max-age=1000; includeSubDomains; preload
- Content-Security-Policy: upgrade-insecure-requests
- Cache-Control: max-age=30, public
- Accept-Encoding: gzip, deflate, br
- Accept: image/webp; imgae/apng, image/*, */*;q=0.8
- Accept-CH: Width, Viewport-Width
- Accept-CH-Lifetime: 100
- Link: </font.woff2>; rel=preload; as=font; no-push
- Feature-Policy: vibrate 'none'; geolocation 'non'
- Remember, PyTorch is an ML library.
- Apparently the purchase offer proceeds are doled out through cash holdings in Solium, rather than between SpaceX and the employee directly. You have to elect between a transfer (which requires bank info) and a check (which requires an address). If you don't elect, it defaults to check. I was out of town with no service, but I received no notification of shipment, so I emailed them today (others said they received their transfers earlier).
- GSW crushed Portland in game 1.
- Promises in JS are just like callbacks (setTimeout, etc), just cleaner. They define two things: what to return when it succeeds (.then), and how to handle the error when it fails (.catch). Resolve vs reject. You can have multiple chained .then calls, executed in order if it no errors are thrown in the previous. You can also fire off multiple promises at the same time (Promise.all([]).
- async is simply a way to return a promise. Then you call await, which blocks until the promise resolves. You can do multiple concurrently with Promise.all() in the same way.
Wednesday, May 8, 2019
- California has a larger economy by itself than every country on the planet except 4: US, China, Japan, Germany.
- Got my POA notarized. Allie will bring to SpaceX tomorrow. We also got the final allocations today. lol.
- Read about all 3 star wars trilogies, 9 movies in total. I have only seen maybe 2 of them, and only when I was a child. Not a fan, but was just curious to read a 10min summary of the entire saga.
- Unloaded amazon fresh and packed the BMW saddlebags full of all LiB food. Packed all regular stuff as well, after laundry.
Tuesday, May 7, 2019
- Supercontest
- Split the uwsgi ini file into proper sections and moved all configuration there instead of as clargs in docker-compose.
- Process
- docker network create nginx-proxy
- docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --name nginx-proxy --net nginx-proxy jwilder/nginx-proxy
- Then start the app containers (usually `make build-start-prod`).
- letsencrypt-nginx-proxy-companion has some useful utilities.
- docker exec nginx-letsencrypt /app/force_renew
- docker exec nginx-letsencrypt /app/cert_status
- Created the bmahlstedt.com github repo. Added a tiny app with tiny landing page.
- Created the infra github repo. Moved the command line process above to a docker-compose and added a readme. Now, you simply docker-compose up there (after creating the nginx-proxy network) just once, and then can create as many virtual hosts as you'd like.
- nginx-proxy is pretty dope. It uses a dummy dhparam while a new one is generated in the background (2048 bits can take a while), then it reloads nginx automatically when done.
- Renamed services (like app_prod) to use dashes instead of underscores (to app-prod).
- Confirmed that app-dev still works.
- After a docker system prune, you need to recreate the network. The volumes will stay by default.
- http forwards to https and www forwards to non-www (just southbaysupercontest.com and bmahlstedt.com).
- Got ssl working with letsencrypt-nginx-proxy-companion. The setup is pretty clean now.
- Updated documentation.
- Closed #47. Everything is done now. There are two containers (nginx-proxy and letsencrypt) that control traffic (and certify) all other virtual host containers on that machine. Right now that includes two apps, southbaysupercontest.com and bmahlstedt.com.
- DHPARAM = Diffie Hellman parameters, used for secret key validation.
- Buyback BS.
- I made my election and submitted the transmittal form separately to SpaceX. This is a dumb requirement in the first place, because you're already making a digital confirmation.
- I played with my election after, knowing that I wasn't going to change it. I just wanted to observe. I intentionally did not submit the transmittal forms for these.
- Because the transmitted number and my solium number did not match, Solium generated incorrect final documents. SpaceX can fix this, but they need my power of attorney since it's technically changing a number after the close date. Ridiculous and inconvenient (requires notary).
- Made an appointment for BOA tomorrow.
- Dad is going in for surgery tomorrow, called for good luck.
- Placed Amazon Fresh order for Lightning in a Bottle - $140. Soylent, protein bars, and almost every non-refrigerated fruit & vegetable you can imagine!
- Tutorials
- Express
- Process
- npm init (creates package.json)
- npm install express (adds it to node_modules/ and the deps in package.json)
- app.js with require, app instantiation, route addition, listen on port.
- node app.js
- This is identical to what I'm used to. Remember, node is the javascript runtime outside the browser (python). Express is the web framework (flask).
- Autoreload behavior can be enabled by `sudo npm install nodemon -g` then `nodemon app.js` instead of `node app.js`.
- Pug (and old-school jade) is the template engine for node, just like jinja is for python. You can render these templates and insert variables and other functionality.
- JS, even with its exponential growth, is still not as full-featured of an environment for enterprise app development as something like java/python/c#.
- Typescript goes a little further than JS because it has static typing.
- OvernightJS is a utility lib for apps build with typescript and express. Gives some nice classes and controllers and decorators.
- Updated resume. Cleaned the skill organization at the bottom. Did a little on linked/github as well.
Monday, May 6, 2019
- JS is, of course, dynamically typed like Python. Types are inferred at runtime. Typescript is statically typed, so types are known before runtime. You can lint this with tslint.
- Python 3 has type hinting (called such because it's optional). You can specify the input and output types a function expects, and then static analysis can catch any errors before runtime. It's also nice for documentation.
- California is about the same latitude as the VERY bottom of Europe, almost between it and Africa. Northern California is about the same as Spain/Portugal.
- Deer shed their antlers every spring and they grow back during summer. I had no idea.
- Started work on the reverse proxy for supercontest and bmahlstedt.com. Will post all details tomorrow.
Sunday, May 5, 2019
- Played around with maintenance banners for a downed website. You basically just have to return 503 so search engines know it's temporary. Then, for users, you can add a custom html template with a friendly, descriptive message.
- Helped jcriss with the grom mods. Bar end mirrors, bunny ear blockoffs with turn signals integrated, fender eliminator with brake and turn signals, sprocket, brake and clutch shorty levers.
- Sliced open my finger pretty bad with an exacto knife while slicing a bundle to rewire.
- Smoked ribs again for game of thrones. This time did NOT use hot sauce as the only marinade! Added a little curry to the rub.
- Got the replacement amex and activated it. Got new insurance cards and put them on all bikes.
- Received my medical identification card and the choice form. You must elect one of the two plans: LA Care and Health Net. They're both HMOs. I choice Health Net because Torrance Memorial Medical Center is under them, my closest hospital (although Health Net's Medi-Cal plan will cover emergency services anywhere in the United States!) I have no intended doctor visits or anything else to sway the decision. Chose Salahuddin Aschrafnia as primary care simply because it's close (Redondo) and decently rated.
- Unboxed the new tent and sleeping pad for LiB, practiced assembling everything (even hitching the guy lines).
Friday, May 3, 2019
- Puppeteer is a popular headless browser webscraper like selenium.
- HN/MD.
- Completely reorganized all of my files in Google drive. This took a couple hours.
- Watched deliverance. It was hyped as one of the most disturbing movies of all time. It was average. The movie was 2 hours long and crawled. There were essentially 3 scenes: rape, river peril, and cliff climbing. It could have been 60 minutes shorter. It was neither shocking nor provocative. The banjo duel was the best part.
- Ordered a single person tent and sleeping pad (totaling $125, but they're good quality and reusable) for lightning in a bottle.
- I get a couple recruitment calls a day. Considering taking my number off linkedin.
- They're starting this new tactic of "we're looking for the best of the best for <X> role, can you recommend one of your colleagues who is looking for an amazing new opportunity?" They manipulate the tone by flattering your altruistic side, seeming informal and taking pressure off the real focus before circling back to your pursuit.
- Supercontest.
- Played around with multiple docker-compose, splitting the dev/prod envs into separate files rather than separate services within the same file. I prefer it the way I had it.
- Had to recalibrate my consideration of the reverse proxy. I'm not adding an nginx container to then forward traffic to multiple other containers running nginx as the server frontend for other app containers. I'm simply taking the existing nginx and certbot containers that serve supercontest, and I'm swapping them for nginx-proxy and letsencrypt-ngnix-proxy-companion so that they can be the webserver for multiple service domains (running in separate other containers).
- Those two containers are therefore abstracted outside of the supercontest project. They probably won't be in a compose file. They'll just be a command to run prior to starting the supercontest containers, with the sc compose file just having the app and the db.
- This is a wonderful compartmentalization, in both technical and general terms. Service administration has advanced wondrously in the past decade.
- Created a repo for my rc files and uninstalled dejadup: https://github.com/brianmahlstedt/config.
Thursday, May 2, 2019
- Supercontest
- Remember, you have to docker-compose down before running the tests on the host. Otherwise, the app will not be able to start (socket already in use).
- Added tests for http auth and the graphql endpoint. CSRF is disabled in the python tests, so I gave a full client example in the readme.
- Stopped using relays and connectionfields, opting instead to just use graphene's List type. You lose some automatic pagination and other cursor capabilities, but querying becomes a lot simpler - you don't have to specify edges and nodes every time. As it grows, switching back would be very easy.
- Deployed to prod and closed #41 after merge. The `make deploy` convenience target works.
- Graphiql in prod was missing the csrf token. I ensured SC_DEV worked and the csrf protection was initialized.
- Changed the makefile recipes for ansible to use --key-file at the command line instead of requiring that ssh-agent and ssh-add be run before.
- Added csrf_protect back to the app in dev mode, then exempted the graphql view. This is just wrapping it with the func (instead of the decorator), like login_required(csrf_protect.exempt(GraphQLView.as_view())).
- Right now, my graphql resolvers just return everything. I don't add nodes and fields for people to filter on certain values. I can later, but right now I just expect clients to handle it all.
- Emailed the group with the graphiql link and the python query example.
- docker top can be used to check processes in the container.
- You can check the environment of an already-running process with `cat /proc/<pid>/environ`. Super useful.
- Removed the ps1 stuff from tmux (it was exiting immediately on startup) and removed the ssh-agent stuff from .bash_profile (I explicitly call out the ssh key in my makefile calls to ansible).
- Nginx reverse proxy.
- Multiple websites in different containers on the same machine.
- First create the umbrella network on the host: docker network create nginx-proxy
- Then start the reverse proxy container which uses this network.
- Then start the actual service containers with this network as well. These must have 3 things in their docker-compose yamls:
- Expose port 80 on the service
- Add the nginx-proxy network
- Add the VIRTUAL_HOST env var for the domain.
- There's a companion container to handle letsencrypt as well.
- Add a few more volumes to share certs between the containers.
- Add the LETSENCRYPT_HOST (and _EMAIL) env vars for the domain.
- Didn't finish this, but will resume tomorrow.
- Generalized my digitalocean project name and droplet name to MyProject and MyDroplet, since they host multiple services. Added the A and NS records for my second domain (bmahlstedt.com), so digitalocean's nameservers direct to both my domains instead of godaddy. The registrar update it within like 60 seconds, much faster than last time.
- Since I haven't finished the reverse proxy yet, https://bmahlstedt.com points to the supercontest application lol. This makes sense, as I'm not VIRTUAL_HOST routing the traffic by domain yet.
- This could be used easily to point multiple domains at the exact same service/site.
- It's also not ssl trusted and red, which makes sense since I haven't certified this domain yet.
Wednesday, May 1, 2019
- Bazel.
- WORKSPACE file defines the root. File(s) named BUILD within that root defines the rules, to point at the input source and define the outputs. You can have multiple BUILD files. Each defines a "package" for bazel. They can depend on each other (need to add "visibility" in the build file), and each can have multiple targets.
- bazel build //path-to-package:target-name
- Say you have a .cc file that prints hello world. Building that target with cc_binary would add it to <workspace_root>/bazel-bin/main/hello-world, which you can then call whenever you want.
- bazel-bin, bazel-genfiles, bazel-out, bazel-* are all just symlinks (in your workspace root) to ~/.cache/bazel.
- You can query dependencies of your targets: bazel query --output graph --nohost_deps --noimplicit_deps 'deps(//main:hello-world)'
- Installed graphviz and xdot, common viewers for many things (including bazel dependency graphs).
- http://www.webgraphviz.com/ is an awesome browser viewer, just copy the text output from the command line. Or, pipe it to xdot at the command line.
- The value here is the entire tree. Everything is a file, and the entire dependency graph is known. Therefore, building outputs (binaries, whatever) can be optimized. When outputs need to be rebuilt, only the inputs that have changed need to be rebuilt.
- For a language like python that isn't built (compiled) manually, but rather interpreted, this has a lot less value. There are four standard python targets. py_binary, py_library, py_test, py_runtime.
- Looked up some more python/bazel suggestions, watched https://www.youtube.com/watch?v=9mhmGcR6CPo.
- Ultimately, not using this for supercontest or any of my other projects. Simple GNUmake and sx-setuptools are wonderful.
- There is value in a monorepo setting, but the hardest part is getting the dependency resolution down to the file level instead of the python package level.
- This becomes impossible fully, because third-party packages will be vendored and you can't specify all of those down to file.
- If third-party packages started defining as bazel packages instead of python packages, we could get somewhere.
- This is all an attempt to define a language-agnostic packaging standard that ultimately just defines file inputs and file outputs.
- Bazel users absolutely love the word hermetic. It means airtight, people.
- Remember, compiling is just translating to a lower-level language (like assembly, bytecode, machine code...).
- Some nix reminders.
- inode is a data structure. It stores metadata like owner, perms, parent dir, last modified, etc. It does not store filename or the actual data in the file.
- Hard links are basically copies. They contain the data. Can only hard link files, not dirs. Same inode. Must be on same filesystem.
- Soft links (symlinks) are basically shortcuts. They do not contain the data. Can soft link dirs or files. Different inodes. Can cross filesystems.
- To nest bullets in github markdown, leave the hyphen and just put 4 spaces in front of it.
- $PS1 is a linux variable that defines the custom shell prompt. It's different within tmux vs outside, hence the lack of color. Tried the top 5 solutions to fix this, none worked. Messed with a ton of bashrc and tmux.conf.
- Nginx can directly serve multiple websites (domains) from the same machine. If you are running your services in a container, then you can also use nginx on the host as a reverse proxy to forward traffic to the appropriate containers (where nginx again can be the server for the app-specific request).
- Bought bmahlstedt.com for $21 (2yr contract) through GoDaddy, same as southbaysupercontest.
- If a website tells you to disable your adblocker, you can often just set style="display:none;" on the banner and then change the background color back to white or increase brightness.
- GraphQL.
- There are a few places in my application where I translate an email to an ID, an ID to picks, picks to scores, etc. GraphQL should be able to help quite well with this over-fetching that REST is vulnerable to.
- Was created at FB in 2012, earlier than I thought.
- graphene and graphene-sqlalchemy are two python packages to aid in use with graphql models. flask-graphene is the extension to add the /graphql view. gql is the client.
- Added the graphql view, with the query schema wrapped around my existing user/pick/matchup models.
- Created the environment variable SC_DEV and set it to 1 in docker-compose for app_dev. This skips csrf protection and enables graphiql in the browser.
- Wrapped the view_func with login_required() for add_user_rule, rather than decorating it like a normal route. You now need to login to hit the graphql endpoint, even programmatically.
- In graphiql, ctrl-space will autocomplete with an option dropdown. ctrl-enter will execute the query.
- You can then query from the command line with curl at /graphql?query=<>
- You can then query from python with gql.
- Since the app has direct access to the database, sqlalchemy is fine to perform internal app queries. To go through graphql for the app itself would be weird and inefficient: python -> http through view -> python.
- I am intentionally not adding mutations. This is a read-only interface for users to mess with the db.
- Graphiql is an extremely useful interface for users to query the db. I had to do some fancy stuff to extend csrf/auth to the graphql endpoint, but I was successful.
- Added two tests. One that verifies that you can auth with the app via basic requests + csrf token (rather than with selenium). The second auths verifies that the graphql endpoint can return data programmatically. This was simply achieve with json={'query': query} where query is a docstring with the same content you'd enter into graphiql. Didn't end up needing gql (bc I couldn't really use it without hacking my auth mechanism for csrf in).
- Ended up enabling graphiql for production, since it's protected by auth anyway.
- Github offers an API to query their data with graphql: https://developer.github.com/v4/.
- Medium obviously collaborates with freecodecamp.org and codeburst.io.
- Alexa (not amazon) is another company that monitors internet traffic. They rank the most popular sites: https://www.alexa.com/topsites. In the US the top 24 are: google youtube facebook amazon wikipedia reddit yahoo twitter linkedin instagram ebay microsoftonline netflix twitch instructure pornhub imgur live craigslist espn chase paypal bing cnn
- JWT = json web tokens.
- Extremely using for programmatically repeating a manual browser request (like a login): open chrome devtools, perform an action, then go to the network tab, right click the request, copy as curl, then convert to python requests with https://curl.trillworks.com/.
- It totally depends on the service, but selenium should be able to login for all because it's closest to a real user. For direct auth with requests, the server can expect whatever it wants. Some require certain cookies (which you can get with a naked request then session.cookies.get_dict()). Supercontest requires a csrf_token to be passed with your credentials, that's it. Make a request, save the csrf token from the response, the hit /user/sign-in with your creds and the csrf token.
Tuesday, April 30, 2019
- MD. Articles on ML and React component testing.
- Jasmine.
- Ahhhh, played with jasmine a bit more. "$ is not defined" and such is because I was using jasmine-node. jQuery requires the browser's DOM api, which node does not have. You have to use the html runner for jasmine (so you can add it as a usual script, from a cdn or otherwise).
- Here is a library that allows you to load html/css/other fixtures into the jasmine context: https://www.npmjs.com/package/jasmine-jquery.
- You could still just run tests with a headless browser to exercise the frontend, which I'm already doing. It's just a bit easier to unittest js functions directly with jasmine.
- Opting to not pursue this further for now, coverage is already sufficient.
- Installed pkg-config zlib1g-dev openjdk-8-jdk bazel
- ipython was busted because of an incompatible version of prompt-toolkit (probably from the jupyter install yesterday), so I reinstalled that package.
- Remember at the ipython prompt you can type ! before a command to execute something in the system shell (useful for pip installations and such).
- Lightning in a bottle schedule was released. Didn't really look at it much, just a quick skim.
- Webscraping.
- (preferable) Use an exposed API, with structure that is designed for programmatic requests of data.
- HTTP with form assistance. Use a library like mechanize or robobrowser to handle all the browser defaults for the form fields you don't care about (everything except un/pw). This handles session.
- Pure HTTP. Use devtools to watch the network activity of your manual request. Copy all the form data. Use a requests session to persist returned cookies and other things across subsequent requests.
- Selenium. Simulate the frontend and perform your usual data entry / clicking.
- Pharma.
- Logged into new.andanet.com and searched for some drug prices, then tried to fetch the data programmatically and serve it in an aggregate marketplace across a few vendors.
- Mechanize doesn't support py3 and robobrowser is newer, so I used that. Both robobrowser and pure requests would not return the login form. "Your current web browser session has been closed due to inactivity. Please login to create a new session." This is likely because neither uses an actual browser, which is an interesting deterrent to programmatic interaction. Let me try with Selenium next.
- Selenium was able to successfully log in. The next problem is the 2FA. It emails a verification code. I could automate this with Selenium as well, fetching the code from email and clicking the second submit, but then we'd need creds to the email account as well. Before trying that, I want to see if there's an easy way to emulate a trusted device.
- There are many parameters a server could use to determine a valid session. It's more than just cookies. Could be MAC, could be timing-related, could be much more. It's a hidden decision by the service that you couldn't figure out without brute forcing. The client can't know.
- Instead, I'll try changing the email to mine and actually following the the 2FA programmatically.
- That worked!
- webdriverElement.click() can be covered by other elements, display off, etc. To force the submission, use webdriver.execute_script('arguments[0].click();', element).
- It looks like I only needed to confirm 2FA once. Even if I close python and the session, selenium is saving something somewhere that is deemed by the anda service as the same trusted device. Could be IP, who knows. This is great news! Could be different for other vendors though.
- Successfully webscraped through 2FA.
- Moved this logic from a script into an app. flask-table. Just a search bar and an updating table.
- Demo marketplace, with only 1 vendor, is complete.
- Used query params (?q=<>) instead of variable args in the route. Just request.args.get(). Very simple and clean.
- Updated link action based on the value of another (input) element, with just HTML. Easy.
- Github shows file details now: i.e. what percent python, what percent css, etc.
- ctrl-alt-shift-r will start/stop screen recording on ubuntu. Amazing. It saves to .webm files, which chrome can open and play.
Monday, April 29, 2019
- The ribs yesterday ended up VERY spicy. The ghost pepper sauce (bhut jolokia) is 150k scoville heat units. I used a lot. Also made sweet potato pancakes properly today.
- Game of thrones was good, but the resolution was too simple. No warging, no myths, no allegiance swapping, no surprises, bad battle tactics, no legendary explanations, no major deaths, etc. The night king isn't apparently the primary antagonist. We're gonna end politically with a human vs human war.
- Python at Netflix: https://medium.com/netflix-techblog/python-at-netflix-bba45dae649e. Their CDN for all media is called Open Connect, but a lot of their service infrastructure is Python (load balancing, ML, automation, monitoring, alerting, infosec, marketing, metrics).
- AWS for hosting, spinnaker for deployment, atlas for monitoring, genie for job execution, winston to pull it all together.
- BLESS = their SSH certificate authority.
- Jupyter
- I've never really found a need for Jupyter notebooks, but they're becoming more essential for data scientists.
- Features
- You can run code, visualize output, execute and tinker all the browser, and more.
- You can basically created parametrized notebooks as templates to allow inputs and output configuration, across many languages (not just python!).
- You can add notes, diagrams, and more surrounding the code.
- There's an API for data in and out of notebooks, for integration with actual services.
- I installed it and played around (via pip into my sys python).
- You can edit local files in the browser, run them, open a generic terminal. Useful stuff.
- You can create a "notebook" which allows you to enter code and markdown together, as before (for reports, for datasharing, for notes, for more!). This saves as extension `.ipynb`.
- Jasmine
- Comparison to python unittesting
- describe = class (like `unittest.TestCase`)
- it = unittest (like `def test_x()` - these are also called "specs")
- expect = assert (there are a ton)
- beforeEach beforeAll afterEach afterAll = setup setupClass teardown teardownClass
- self = this (persists across tests)
- spies = mocks
- `jasmine server` allows you to iterate your tests in the browser. `jasmine ci` uses selenium to run for builds.
- While jasmine focuses on being a test framework (for describing the tests, like unittest), karma is a very popular js testrunner (for execution of the tests, like nose).
- Supercontest
- Separated all python and js tests into distinct make recipes. The python suite still enters with tox, while eslint and jasmine run for js.
- Globally installed nodejs and npm (although not using for anything right now).
- Added the jasmine infra and a basic test. My js isn't very complicated so I was intentionally light here. I could organize some of the event callbacks into separate functions to be tested, but it's fine in scope for now.
- Closed #20 after lots of testing! Pylint, pytests, eslint, jasmine.
- Modified my app dockerfile to use joyzoursky/python-chromedriver directly instead of pulling the python base image and installing chrome/chromedriver/selenium in the dockerfile.
Sunday, April 28, 2019
- A king cobra bite can kill an elephant!
- Bought and prepped 2 spare rib racks yesterday. Smoked them today for game of thrones. Getting much better at trimming, especially with focus to both the tips and the st louis cut.
- Shopped for motorcycles at a few shops with jcriss yesterday, he brought a grommmm.
- WAF = web application firewall.
- BitMitigate is a cool service that provides ddos protection, waf, cdn, and more.
- To get the thumbnail from a youtube video, just enter the ID into: https://img.youtube.com/vi/<>/maxresdefault.jpg
Friday, April 26, 2019
- Supercontest.
- Added pytest-cov. 45% overall. Not bad! Most of the core functionality is covered.
- JS lint/tests.
- Activate your python venv, then pip install nodeenv, then run nodeenv -p. This creates a virtualenv for node modules integrated with your current virtualenv for python modules. Gives you the `npm <>` command.
- ./node_modules instead of ./venv. Has a bin and all the usual. This should be gitignored. The package-lock.json should not.
- `npx` can be used instead of `npm` at the command line. This will fetch packages as needed into tmpdirs and run them.
- Instead of coupling it with python/tox, you can use `nave` to create a pure node venv, and then add make targets to execute whatever test commands (instead of tox).
- You can also run through npm itself, by defining a lint task in package.json (setup.py) and `npm run lint` (pip run lint). I've never like coupling the package manage with the admin commands. An external infra like make is better for this.
- Ran npm init to create a skeleton package (required for style guide).
- Ran eslint --init to create an eslintrc.json.
- Ran a full eslint evaluation! 113 errors in my 4 simple files. Extending Google style guide. Common fixes I performed:
- Single instead of double quotes.
- Const instead of let for vars that are never reassigned.
- No double space before inline comment, like Python.
- Regular line indents are all 2 spaces. Indents for line continuation are 4 spaces.
- No space between function and ().
- Trailing common after the last item in sequences.
- jasmine init, then added the spec yml to vcs.
- Creed from The Office is performing at Saint Rocke on June 29: https://www.ticketweb.com/event/creed-bratton-saint-rocke-tickets/9166055?pl=saintrocke. It's not comedy, it's music: https://www.youtube.com/watch?v=Vt6kcF-PIsE.
- HN. Some mild interest this week.
- Removed the js blocks from vimrc. Didn't like the folding.
- JS speed is important, obviously, because of clientside implications. Hence the preference for 2 spaces instead of 4. JS typically isn't compiled or compressed, so this small percentage makes a little difference. Also, with tons of callbacks, 4 spaces can visually get way too indented.
- PharmaDB
- Talked a little with Art about aggregating prices into a central marketplace, like Kayak for drugs.
- Currently, technicians spend a lot of time shopping around for the lowest prices. Pharmacies (or their parents) have contracts with vendors which change the prices. These are reflected in the account, and work automatically with the creds to log in to the vendor site.
- Some common vendors: AmerisourceBergen, Cardinal, HD Smith, Anda, Parmed.
- Medicaid hosts a database with (I assume) average prices: https://data.medicaid.gov/Drug-Pricing-and-Payment/National-Pharmacy-Pricing-Database-xls/uima-szn8.
- Gonna try to get a demo account (can only see prices, not order) to write an app that fetches all this information and aggregates it in a simple marketplace platform.
- Sugar caramelizes at about 340F. If you're doing low and slow ~200, it's fine. I prefer a bit of brown sugar in the texas crutch. And don't worry about bbq sauce on ribs if you're cooking low. Do not use sugar/bbq sauce for hot and fast.
- Prepared the rib recipe for sunday. Going to focus on the rib tips this time instead of the st louis cut (still doing full spare racks). That's cartilage in the tips, not bone!
- Lots of info came for lighting in a bottle. Skimmed most of it.
- Pivotal, the company Rachel came from, makes RabbitMQ and Jasmine. They're owned by Dell. I knew neither of these facts.
- Csslint is also a thing.
- Finished the suspiria remake (2018). I watch a lot of horror movies, and I loved how different this one is. That ENDING whattttt.
- If you have chrome devtools open on a tab, you have a LOT of data. If you login to a site, the network tab shows you the form data of the request, which literally contains your plaintext password. This can be recorded (for that tab only). After that, it's obviously stored in a cookie so that subsequent requests don't contain the password. Still, given all that information, another client could copy and imitate that request.
- Sharks and Warriors playoff games.
- Remember, TDD = Test Driven Development and BDD = Behavior Driven Development.
Thursday, April 25, 2019
- Avengers Endgame. I've never been a fan of comic book movies. This one had a ton of hype, almost Avatar level. It was average. There is a lot of time travelling and then a big fight and they knock some stones off his glove and win. Who could have predicted such a shocking, unlikely ending.
- PW: some cool app ideas to practice skills: https://medium.freecodecamp.org/here-are-some-app-ideas-you-can-build-to-level-up-your-coding-skills-39618291f672.
- Supercontest.
- Unittests.
- Had to `sudo systemctl restart postgresql` on my host before running the unittests. Remember, it requires an existing supercontest_unittests db. And remember, I do dev on this laptop as well, so postgresql doesn't start on boot on my host (it would conflict with docker since I use default ports). Laptop must have died at some point.
- Used spoof_lines and spoof_scores to populate the test db.
- Had to install chromedriver on my host (unfortunate dep of the test now, I can fix later but it's not urgent).
- Added selenium capability to the tests so that I can actually check the data in the dom after js runs. I don't do any click functionality to test registration or anything, just verification of the route APIs.
- Changed to LiveServerTestCase from flask-testing so that I could use selenium. self.get_server_url is offered now. This slows down the tests a bit.
- Loving selenium so far for unittests. Load a page, submit for data, click buttons, check results.
- The webdriver API: https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webdriver. find_element[s]_by_[id,xpath,css_selector,name,class_name,link_text].
- Changed commit_picks to allow bypass of all checks (on the python app side).
- Did some color mapping between names and rgba values (which is what selenium returns for the background-color css property).
- Finished all the python tests that I wanted: user/line/score/pick commit, frontend login, matchup/pick/leaderboard view. Now on to eslint and jasmine for the js.
- Docker
- There's an image on dockerhub with python/chromedriver/chrome/selenium: joyzourski/python-chromedriver. Switched to that instead of basing off python and installing the webdriver functionality manually in the dockerfile.
Wednesday, April 24, 2019
- FW/MD
- Function declaration (definition) vs expression (anonymous). Obvious differences. Former allows a variable of global scope for callbacks, hoisting, etc. Latter less mem.
- Change detection in a project usually means VCS changes for CI. Change detection in an app usually means frontend or backend. How does the view/controller respond when the model changes data?
- In docker, `expose` in the dockerfile is just for documentation. `publish` (-p at the cli) is necessary to actually make the ports available. In docker-compose, `expose` in the yml is sufficient to do both.
- Facebook internals. https://www.wired.com/story/facebook-mark-zuckerberg-15-months-of-fresh-hell/. Didn't read the article because it's way too long, but looked interesting.
- The sharks/vgk game 7 last night was the best hockey game I've ever seen. The sharks came back from a 3-0 deficit by scoring 4 goals on a power play due to a 5m major. The knights tied it and pushed it to overtime, where the sharks scored to win. This sealed game 7 after coming back from a 3-1 game deficit in the series.
- The Damian Lillard buzzer beater last night was also one of the best shots I've even seen. 37' out, at 0 seconds, against Paul George, when tied, to end the series and knock OKC out of the playoffs.
- Ordered new shoelaces. 54" just for ref (medium high boots).
- Jury duty summons can pull from registered voter pools or driver's license pools (or both).
- The "utm" you always see in ref links (like HN) is "Urchin Tracking Module". Urchin is the predecessor to Google Analytics, and is simply a marketing tool. These 5 query params (utm_*) can be added to a URL to collect data: source, medium, content, campaign, term.
- Did a couple typing tests. I'm about 90wpm with 95% accuracy.
Tuesday, April 23, 2019
- Reapplied thermal tape to the compressor on the ducati yesterday to protect it from the exhaust pipes.
- Dodgeball championships last night, was great playing with the team. I liked this group (cowbell).
- Went to Slab (same as Trudy's) BBQ today. Brisket was better than Bludso's, chicken was about equal, and pulled pork sucked. They also didn't serve chicken quarters, only halves, which is dumb. Total was $33, which is absolutely ridiculous - that's the same price as an entire 10lb packer of USDA prime. Very thankful I learned to smoke at home. It's better quality at about 1/10th the price, for the sacrifice of a little effort!
- Soundcloud requires you to pay for premium mode to download tracks for offline.
Friday, April 19, 2019
- Supercontest
- Scrubbed testing.postgresql. Wasn't configurable enough for my tests. Couldn't do stuff like changing the default encoding of the db, so collation in the static model failed. Instead, I just defined a separate uri for test (with proper cleanup) and piggybacked off the host postgres installation (which is obviously then required to run tests....system dep agh).
- Removed the collation=NOCASE remnant from sqlite in my models. Then I was able to get a successful unnitest env working. Test app connected to test db.
- The problem now is alembic. The migrations require a local postgresql instance, so I can't run them nominally on the host - I need to run them in the context of the container. Alembic enters through flask-script, which runs on the app container. So you can run a migrate operation while just connected to one container. But the upgrade operation needs the migrate.py from the app container and the actual db from the postgres container, so who knows how that will work. I'll have to look up the right way to use alembic with docker.
- I guess you'd run the manage.py migrate/upgrade commands through docker-compose exec, not on the host. Ok.
- Didn't end up having to migrate since postgres doesn't need the collation, but for future reference: `python manage.py db migrate/upgrade` needs to be run through `docker-compose exec app_dev/prod` now that you're working in a container setup.
- Testing.
- Added extra_config_settings to get_app(), allowing direct flask args to be passed from elsewhere (like tests, where I suppressed mail and csrf).
- Added tests to make sure all the user routes (login/profile/logout/etc) work.
- Debugging.
- You can run `python -m pdb <myscript.py>` or just put `breakpoint()` in your code.
- Then you can step through with s.
- To print, just use `p <var>`.
- You can also check types, specify new variables, etc! `pp locals()` or globals as well.
- `l` or `where` will list where you are in the script.
- `exit` finishes.
- Remember, a lot of system binaries (like echo) are at /bin, not /usr/bin or /usr/local/bin.
- Security.
- Bandit is a cool tool I started playing with: https://github.com/PyCQA/bandit.
- Added to supercontest tox. I had no issues, just two (example) passwords I had to ignore with # nosec.
- Internet fiasco.
- They wouldn't activate the new account because the modem (which I own, not spectrum) is still attached (maybe mac address) to the old account. After calling them and getting transferred 10 times, and briley doing the same, we finally got it working.
- In the meantime, I went to a few Hermosa cafes for wifi. The new yellow one doesn't offer public internet (lol) and gum tree gives out temporary codes which provide access for an hour (lol). What happened to cafes?
- Indian BBQ.
- My two favorite cuisines on the planet. Had a thought the other day they I might try some fusion with my smoker at home. Did some research, and nothing came up. I don't think it's a very common idea, since the origins of BBQ are the south, and there's not much overlap between the south and India, at least culinarily. High-level smoked meat with curry-based rubs....sounds delicious.
- Started first batch today. Curry jerky! Thinly sliced cross rib roast with some premix curry powder. I can play with the levels and finetune later.
- My xps13 ubuntu18 suddenly couldn't play sound and just showed "dummy output". Running `pulseaudio -k && sudo alsa force-reload` fixed it.
- HN
- Awesome statistical model of skittles: https://possiblywrong.wordpress.com/2019/04/06/follow-up-i-found-two-identical-packs-of-skittles-among-468-packs-with-a-total-of-27740-skittles
- Mentor, don't hire. Workplaces of growth are much better investments. https://sizovs.net/2019/04/10/the-best-developers-are-raised-not-hired.
Subscribe to:
Posts (Atom)