Standing on escalators

In Ayala, there’s this escalator that always pisses me off.
Not so much because it’s a one-lane escalator (in Ayala!), but because inevitably
there’s going to be someone who’ll stop walking and thus forcing everyone
to just stand there and wait.

“Maybe, she’s just tired.”
“Maybe, his legs hurt.”
“Maybe, she’s having girly pains.”

Oh the thoughts that I force myself to think to calm myself down.

Then the slow ride is over and I’m calmed down.

Good thing that the next platform has twin, dual lane escalators.
Then somebody stands in the left lane of the “fast lane” elevator.

Rage.

2014

It’s 2014.

This year will be a year of building up habits.
Building up the ones that I’d like to have.
My goal, at the end of the year, is to have these habits built up:

  • Workout
  • Sleeping/Work
  • Hygiene

Just 3 things.

Workout/Diet
I’ve managed to find a workout routine to stick to.
It’s simple and easy to follow and it’s beginner-friendly. I hope to follow through with this until my membership expires on April and by then, should have a good enough habit base that getting a continuing membership is a no-brainer. I’m happy to teach anyone who’s interested in the program. :)

Diet is still a tricky thing for me. I’m getting back into recording my meals in My Fitness Pal.

Sleping/Work
Sleeping/Work habits is just different sides of the same coin. Right now, I wake up at around 10 to 11 AM. I’m only able to work by 2pm and I stop at around 6pm until 12 midnight, where I go to the gym between 10PM and 12MN. From there, I try to get into the flow again until I become sleepy, which is around 2 to 3AM. Oftentimes, I’m left with the feeling that nearly my whole day went out the window.

I want to change that habit to something like: Wake up at 5AM, work until 8AM, have breakfast, work on non-coding stuff between 9AM until lunch, 1PM to 4PM should be coding work again and the rest of the day will be spent on dinner, gym and leisure. Not married to the actual times, but it’s more of being awake more in the day and spend more of the evening actually sleeping. I actually like being up early in the mornings. I just don’t like getting up.

I also want to incorporate daily reviews to what I’ve accomplished in the day and what I need to do the following day.

Hygiene
I’ve got my hygiene regiment down, I just have trouble sticking to it every time.

Okay, I’m sleepy!

Have a happy new year everyone!

Making Squid a transparent proxy

..has absolutely nothing (almost) to do with Squid.

It’s a single firewall rule like so:

-A PREROUTING -p tcp -m tcp -i wdev0ap0 --dport 80 -j DNAT --to-destination 127.0.0.1:3128

That’s an IPTables rule, normally but Arch (at least the version I was working with) was using UFW so that goes inside my before.rules in /etc/ufw/before.rules, right at the top.


*nat
:PREROUTING - [0,0]
-A PREROUTING -p tcp -m tcp -i wdev0ap0 --dport 80 -j DNAT --to-destination 127.0.0.1:3128
COMMIT

Make sure to restart ufw.

ufw disable && ufw enable

From Squid side, you just have to make sure that Squid is listening to a port transparently.
Change
http_port 3128
to
http_port 3128 intercept.

That should do it.

—-

I wanted to use a FQDN for the splash page though, so we used DNSMasq for DNS.
pacman -S dnsmasq

Then we just edit the /etc/hosts file and put in the FQDN that we want to map to the local IP (not localhost). Of course, this only ever works if your device has a static IP (which it should).


#
# /etc/hosts: static lookup table for host names
#

#
10.1.0.1 rystraum.com
127.0.0.1 localhost.localdomain localhost
::1 localhost.localdomain localhost

# End of file

In order for you to use the DNS on the device, you have to make it your first/default DNS. So, configure that on your network settings.

From here, I can change the Squid splash page config accordingly based on where my allow access page is.

Next steps:

  • Pass along default DNS setting during DHCP
  • Start squid and dnsmasq on startup
  • Remove Node.js apps from startup
  • Install Nginx
  • Map default Squid error page from the static HTML error to default web server on localhost (might not be needed)
  • Dealing with SSL on a transparent proxy setting
  • Changing upstream from eth0 to usb dongle

Thanks to Madumlao for all the help. :)

Squid Splash Page Notes

I’m playing with Squid and setting it up as a captive portal.
This is my notes on their documentation.

  • Top-down processing of rules gave me 90% of the troubles I encountered.
  • The deny_info path doesn’t really work. It should be a filename relative to the error_directory directory.
  • You have to manually create the session db/session folder the first time. mkdir /var/lib/squid/session && chmod 777 /var/lib/squid/session
  • To clear sessions from the server (for testing), you can delete and re-create the sessions folder: rm /var/lib/squid/session -r && mkdir /var/lib/squid/session -r && chmod 777 /var/lib/squid/session
  • Always check permissions.

Next things to do:

  • Making it a transparent proxy
  • Dealing with SSL (port 443)
  • Changing upstream providers from LAN to USB Dongle

http://www.andybev.com/index.php/Setting_up_a_captive_portal_from_scratch_using_Debian
http://system-admin.xtronix.in/2012/07/captive-portal-with-transparent-proxy.html
https://wiki.archlinux.org/index.php/squid#Installation

Here’s a copy of my squid.conf:

#
# Recommended minimum configuration:
#

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT

#
# Recommended minimum Access Permission configuration:
#
# Deny requests to certain unsafe ports
http_access deny !Safe_ports

# Deny CONNECT to other than secure SSL ports
http_access deny CONNECT !SSL_ports

# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager

# We strongly recommend the following be uncommented to protect innocent
# web applications running on the proxy server who think the only
# one who can access services on “localhost” is a local user
#http_access deny to_localhost

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

# Squid normally listens to port 3128
# http_port 3128 transparent
# http_port 80 vhost
# http_port 3128 intercept
http_port 3128 intercept

error_directory /makubex

# http://wiki.squid-cache.org/ConfigExamples/Portal/Splash
#### Passive ####

# external_acl_type splash_page ttl=60 concurrency=100 %SRC /usr/lib/squid/ext_session_acl -t 7200 -b /var/lib/squid/session.db
# acl existing_users external splash_page
# http_access deny !existing_users
# deny_info 511:splash.html existing_users

#### Active ####

# external_acl_type session ttl=300 negative_ttl=0 children-startup=1 concurrency=200 %LOGIN /usr/lib/squid/ext_session_acl
# acl session_login external session LOGIN
# http_access deny !session
# deny_info http://rystraum.com?url=%s session

external_acl_type session concurrency=100 ttl=3 %SRC /usr/lib/squid/ext_session_acl -a -T 10800 -b /var/lib/squid/session/
acl session_login external session LOGIN
external_acl_type session_active_def concurrency=100 ttl=3 %SRC /usr/lib/squid/ext_session_acl -a -T 10800 -b /var/lib/squid/session/
acl session_is_active external session_active_def
# acl clicked_login_url url_regex -i http://rystraum.com$
acl clicked_login_url url_regex -i http://rystraum.com/search$
http_access allow clicked_login_url session_login
http_access deny !session_is_active
deny_info 511:index.html session_is_active
# deny_info http://10.1.0.1?url=%s session_is_active
# acl clicked_login_url url_regex -i http://google.com$

##### Catch All #####

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy
http_access deny all

# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /var/cache/squid 256 16 256

# Leave coredumps in the first cache dir
coredump_dir /var/cache/squid

#
# Add any of your own refresh_pattern entries above these.
#
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320

visible_hostname makubex

Using Dropbox Chooser within ActiveAdmin

We use Dropbox quite heavily in Loudcloud. I’m working on an internal CRM system and since all of our files are on Dropbox anyway, I figured it would be super helpful to just have to link to our Dropbox files.

Here are the relevant files:

# app/inputs/dropbox_input.rb
class DropboxInput < Formtastic::Inputs::FileInput
  def to_html
    input_wrapping do
      label_html <<
      builder.text_field(method, input_html_options.merge({ type: "dropbox-chooser", style: "visibility: hidden;" }))
    end
  end
end

# app/admin/invoice.rb
ActiveAdmin.register Invoice do
  form do |f|
    within @head do
      script src: "https://www.dropbox.com/static/api/1/dropins.js", id: "dropboxjs", type: "text/javascript", "data-app-key" => "APP_KEY_HERE"
    end

    # ....

    f.inputs "Official Receipt" do
      f.input :or_file_url, as: :dropbox, label: "OR File URL"
    end

    # ....
  end
end

Resources:
https://www.dropbox.com/developers/dropins/chooser/js
http://stackoverflow.com/questions/12809237/insert-specifics-js-in-the-header-of-some-pages-active-admin
https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/inputs/base/html.rb
http://stackoverflow.com/questions/12465020/getting-formtastic-in-activeadmin-to-use-custom-form-input-builder

Nested forms with polymorphic association in Active Admin/Formtastic

I spent nearly the whole day making this work.

Given models:
Invoice, has_many :items
Item belongs_to :itemizable, polymorphic: true
Domain & Service has_many :items, as: :itemizable

The problem was multiple things:

  1. The automagic of Formtastic can’t detect the collection if it’s a polymorphic association
  2. Formtastic doesn’t really play well with non-existent attributes

Initially, I’ve thought of just doing:

ActiveAdmin.register Invoice do
  form do |f|    
    # ...
    f.has_many :items do |item|
      item.input :itemizable, collection: (Domain.all + Service.all)
      item.input :quantity
      item.input :price_per_piece
    end

    f.actions
  end
end

But this fails because 1) domains and service can share the same id and 2) I have no way to tell what the item was.
A few hours in and I was going nowhere. It’s surprisingly hard to look for anything related to polymorphic associations on Formtastic. This post gave me an idea however.

So, I’ve thought, why not just hold the id temporarily on an accessor attribute and just do the assignment from a callback before validation kicks in based on which attribute it went into? Raise an error if both were filled up.

It worked! I can now save new polymorphic records. (look at Item#assign_itemizable)

There’s a small problem however. The form to edit an existing record doesn’t pre-populate the corresponding select dropdowns. The solutions was rather simple, override the reader method to return the id of the itemizable if the itemizable is a member of the class.

Maintenance-wise, everything here would add overhead for every new itemizable model I would associate to item, but overall, I think it was a pretty elegant hack. *pats self at back*

Here’s the complete code:

# app/models/invoice.rb
class Invoice < ActiveRecord::Base 
  has_many :items

  accepts_nested_attributes_for :items
end

# app/models/item.rb
class Item < ActiveRecord::Base
  before_validation :assign_itemizable

  belongs_to :invoice
  belongs_to :itemizable, polymorphic: true
  
  validates :itemizable, presence: true

  attr_accessor :itemizable_domain, :itemizable_service

  def itemizable_domain
    self.itemizable.id if self.itemizable.is_a? Domain
  end

  def itemizable_service
    self.itemizable.id if self.itemizable.is_a? Service
  end

  protected
  def assign_itemizable
    if [email protected]_domain.blank? && [email protected]_service.blank?
      errors.add(:itemizable, "can't have both a domain and a service") 
    end

    unless @itemizable_domain.blank?
      self.itemizable = Domain.find(@itemizable_domain)
    end

    unless @itemizable_service.blank?
      self.itemizable = Service.find(@itemizable_service)
    end
  end
end

# app/admin/invoice.rb
ActiveAdmin.register Invoice do
  form do |f|
    f.inputs "Invoice" do 
      f.input :customer
      f.input :invoice_number
      f.input :issuing_person
      f.input :issued_on
      f.input :remarks
    end
    
    f.has_many :items do |item|
      item.input :itemizable_domain, collection: Domain.all
      item.input :itemizable_service, collection: Service.all
      item.input :quantity
      item.input :price_per_piece
    end

    f.actions
  end
end

Edit: Fixed a bug in Item because I overwrote the accessors, which were being called in the validation. This caused a sort of chicken-egg situation, and ultimately causes the validation to fail all the time. Changed .empty? to .blank? so it doesn't barf out on nils.

The key to happiness: a good bed, nice chair and healthy food

If you want to spend on yourself, here’s what I suggest you spend on: A good bed, nice chair and healthy food.

(Ha! I bet you didn’t see that coming!)

This image would explain everything.

Yes, that's the same image as the featured image.
Mmm. Pie.

My list of “things to spend on to invest in myself” is much longer. Those were the top 3.

Breakdown

I amortize costs over the lifetime of the product. I often say, if I spend X amount on this and it lasts me Y (months/years), then I’m just paying Z per (minute/day). Sometimes, I say, if I spend X amount on this and I use this Y number of times, then I’m just paying Z per use when applicable. This way I can compute costs on a daily/monthly/basis.

I’m a believer of YAGNI so I don’t really buy the latest and the greatest (read: most expensive) unless I need them. I fall right in the middle/upper-middle most times. Just enough for my needs, and some bells and whistles.

My longer list with approximate cost ranges is as follows: (All figures in Philippine Pesos)

  1. Good bed, read: mattress (3k to 9k over 3 years or 2.75 to 8.25 per day)
  2. Nice chair (2k to 6k over 2 years or 2.75 to 8.25 per day)
  3. Healthy food (200 to 300 per day)
  4. Flattering clothes (15k to 20k over 1 year or 41.00 to 55.00 per day)
  5. Fluffy pillows (500 to 1k over 1 year or 1.50 to 3.00 per day)
  6. Decent Keyboard & Mouse (1k to 2k over 1 year or 3.00 to 6.00 per day)
  7. Good enough desktop/laptop (20k to 50k over 3 years or 18.50 to 45.75 per day)

I’ve prioritized the list using these reasons:

  1. Bed: The effects of quality sleep affects your every waking hour.
  2. Chair: Good posture is a sort of “prevention is better than cure” thing. More short term, it helps alleviate building up of stress which would affect your quality of work. This also contributes to quality of sleep.
  3. Food: It keeps you alive. Why not spend on it?
  4. Clothes: Find the kind of person that you want to be, and dress like him/her. Imitation is the highest form of flattery or Dress for the kind of job you want, not for the job that you have. The clothes make the man. Or it doesn’t. This deserves its own post.
  5. Pillows: Goes with the bed.
  6. KB&M: My hands are my bread & butter. RSI and CTS can be literal career-ending injuries.
  7. Workstation: I spend at least 8 hours on this thing. I would want to have enough for what I need.

That comes out to 269.5 to 426.25 per day or 8,085.00 to 12,787.5 per month. [1] Factor in bills, rent and other consumables and you’re looking at close to 15,000 to 20,000 per month to live a comfortable life. [2]

I’m at this point in my life wherein I’m content, materially, with everything I have so far. The only significant purchases I have left are a laptop replacement, a vehicle and a house. The last 2 are just luxuries with my current lifestyle and wouldn’t probably buy them for myself anytime soon (i.e. in the next 3 years).

Optimizing for happiness

Happiness is having everything that you need in the world. The first step to being happy is finding out the minimum that you need. It’s entirely subjective.

The next step to happiness is optimizing the these things that contribute to your daily well being. If you feel well enough on a daily basis, then I think you’re 80% there to general happiness. [3] The rest is tougher to crack: healthy relationships, sense of purpose, et al. But it sure becomes easier once you’ve got a solid base.For the low low price of Php 20,000 a month, I can pursue the rest of my 20%.

Am I happy? Currently, yes. But it’s a process.


[1] I actually have another round of computation, wherein the costs are weighted based on how much I use the thing. I’m being lazy so I didn’t include it.

[2] This is for a single, no dependents person. For a family that is sharing a lot of the things above including rent and utilities, this would be significantly less per person. But of course, you’d have to multiply per head so it comes out larger in lump sum.

A totally pulled-out-of-my-ass formula is : x = number of people, amount = x * 20,000 * (0.9 ^ x). This yields:

1 20,000.00
2 32,400.00
3 43,740.00
4 52,488.00
5 59,049.00
6 63,772.92
7 66,961.57

[3 ]Pareto principle, the 80-20 rule. Generally speaking, 80% of output, comes from 20% of input.

Motivation and Decision-making

I like reading about psychology. Especially psychology related to motivation and decision-making.

Here are some links that I find myself visiting time and again. Some of them, I can relate with (to some degree) while others are references I come back to time and again.

Featured image care of Marco Bellucci

Obligatory Birthday Post — 24 of ???

It was more of a birthday weekend, more than anything.

I did not have any plans whatsoever. All I knew was that I was pretty tired because of the week that just ended.

I’d like to thank everyone who were there during my “surprise” birthday party.

My labs, Angel — thanks for the birthday gifts and for all the love. <3
Our head honcho, Ma’m Deng and Julianne — double thanks for arranging everything!
Joanna and family
Madumlao and Alex — thanks Mark for the cake!
Jerix, Gerry, JP and Liz
Karl, Allan, Jeffrey, Rexell and Tandz
Kenan and Matt

I spent the whole of Aug 18 with my family and my dogs. We went out and watched Percy Jackson.

It’s raining pretty hard outside though.

I’ve got a lot more in my mind, but I’m sleepy.

The Un-fun game of eRepublik

I play Erepublik and have been playing consistently for quite some time now.

Okay, playing is probably an overstatement. It’s more accurately described as I’ve-been-logging-in-and-clicking-around-10-times-before-logging-out. It’s an exercise in patience.

After doing the usual routine (which takes me probably a minute), I always stop and think what exactly this game is missing. It’s got a very engaged community, decent UI and I would presume sustainable enough sales.

It’s not fun.

Trading effort for progress

There’s only trade a lot of money for a little bit of progress.There’s no mechanism for me to put in effort to gain a little bit more of progress ahead of everyone else that does the bare minimum (login, work + train).  This kind of reminds me of Neopets at the other extreme, where there’s just so many things to do that you can easily sink a whole day in it and not be done with everything you can do daily.

Some of my ideas here are:

  • Side stories / side quests
  • Make training much more interactive
  • Make working much more interactive

Predictability

One other thing that makes it not-fun is that everything is predictable. There’s absolutely no chance involved. The larger a country is, the more population it has, the more resources it produces, the more territory it can conquer. This is a 100% sure thing.

On the other hand, small countries’ (like ePH) resistance wars is an exercise in futility.

What a huge thing a +- (1-10)% random bonus per war could give both sides. It would make war strategy much more exciting other than “I need to have more people/energy bars than the other side have.”

Some of my ideas here:

  • War module: random bonus/penalty (based on RL weather?)
  • Economy module: production bonuses/penalty (based on RL stock market?)

Simplicity

Erep’s simplicity undermines its potential.

The economy sucks because it’s too simple. There’s not enough room for players to turn a profit. The only ways to turn a profit is either build Q6-Q7 weapons factory and hire other people or buy from major markets and sell in smaller markets.

The war module kind of sucks because it’s too simple. There’s not much strategy further than “we need to find more high str players with lots of bars/weapons than the other side”.

Daily activities suck because it’s too simple. I just need to go work for the highest bidder and work everyday (read: click the work button). I just need to level up my training grounds and train everyday (read: click the train button).

The political system sucks because it’s too simple. Everything is entirely subjective and lawmakers are not given insight to country data to effectively address macro-level issues. Analytics over time would be a huge boon to proper lawmaking.

“Make it as simple as possible, but not any simpler.”


Erepublik is kind of enviable in a way that despite the game’s deficiencies, people still stick to it. It’s community finds fun within its own meta-game. For a game developer however, I think that’s a pretty pathetic state to be in.

Hopefully, there’s no other way to go but up. Unless Plato suddenly gets one of his bright ideas.