Home Archive Wiki About
Home Archive Wiki About

Home

2018-12-09 - It might be interesting to have a realistic planning system

There’s many different kinds of things to do

There’s a bunch of things I want or need to do, and they have different shapes.

  • Some can be finite sequences of actions. Thing like this are for example “move to a new apartment”. You have actions like “get moving boxes”, “look into moving options”, “pack these things into this box”. You have dependencies like “you can only unpack if you have already moved the boxes to the new place”, or “you need to order the boxes online before packing them up”. When you finish all the tasks, you are done, and you can forget about the problem forever.
  • Some are basic needs, like the need to sleep or the need to get food. If I don’t get sleep, I am slow, and will eventually fall asleep no matter how much I try to stay awake. Unlike moving to a new apartment, I will always need to sleep. I can’t, say, sleep for 24 hours and then go awake for a whole week.
  • Some things take a long time and are open-ended, like learning a language. There will be a time when I will be competent enough, but it will take a lot of practice, and cannot be practically modelled as a finite sequence of steps.
  • And more advanced needs, like “I want to do something fun” or “I want to hang out with friends”.

Productivity methodologies I know about are way too narrow

There’s a bunch of methodologies for productivity, but I feel they often only model a small part of planning. For example, (my interpretation of) GTD puts everything in a framing of “you have Projects and projects have Actions”. But I don’t think that’s a good framing for, say, learning a language.

The model of “cost of time” is also wrong. It is a useful heuristic, but the value you assign to any activity is going to assume perfect elasticity. For example, you cannot just walk up to your employer and say “I want to work 120 hours per week”. No (reasonable) employer will say “yes” to that. Also, the many things a person wants cannot be converted into a one-dimensional value. (Footnote: Yeah I know about von Neumann-Morgenstern theorem. But people are not rational agents, and von Neumann-Morgenstern does not say anything about how practical will the resulting utility function be to evaluate.)

What I tend to do is some sort of intuitive “higher-level planning” which is sometimes a bit reflective, but not very often. When I’m in “work mode” (i.e., in my actual job), I have a few ways I try to figure out what to do on any particular day.

But the process by which I decide, say, “enough work today, let’s go get some sleep”, or maybe “I’m a bit tired but let’s go walk on the treadmill for a while”, is very intuitive.

I don’t know about any formal methodology which would basically take an input like:

  • I need to work so I get money and feel good;
  • I also need to sleep roughly 8 hours daily;
  • I need to have some fun;
  • I also want to learn German; and
  • I need to do a bunch of multi-step things before their deadline,

and which would output a plan of what I should be doing at any given time.

And I would like the plan to be reasonable. The methodology should not, for example, assume I can do without sleep, or without a regular sleep schedule.

And that’s what I mean by a “realistic planning system”.

Maybe good old fashioned AI-style planning could be adapted?

In uni, I studied a bunch of planning and scheduling, which is mostly used for cases like “this is how you construct a submarine; you can’t screw in screw B217 until you screw in screws B210-B216; make a schedule which takes as little time as possible”.

These algorithms can be extended to work in more general environments, like:

  • Some people have working hours and when a worker is not working, you can’t plan jobs for them.
  • There’s limited resources, like “you need a drill to drill a hole and there are only 10 drills; you can’t have more than 10 workers drilling at the same time”.

I wonder if you could make a realistic and formal planning system from some extension of that setup. Say something like:

  • There is a “sleep meter”. If sleep meter goes to 0, agent must sleep for 8 hours. “Sleep meter” slowly goes down during the day.
  • There is some sort of penalty on effectiveness when underslept or when sleep is irregular.
  • Different types of actions deplete other types of meters. Light socialization depletes “introvert points” (for me). Snuggles increase “oxytocin meter” (which is a dimension of “happiness”).
  • And there could be some modelling of “if you get too tired you have to sleep”. Perhaps the algorithm would compete for control with “drive to sleep”, and the lower the sleep counter is, the higher the likelihood the person just falls asleep wherever they are.
  • And I think it would be nice if the algorithm treated all “needs” symmetrically. According to internal family systems, people have many relatively smart parts good at different things and wanting different things. If the system is cooperative and does not place any particular part at a “command” level or at a “subordinate” level, it would hopefully make it easy for parts to agree to collective decisions.

Meh, too hard. I got other stuff to do.

I guess getting any model halfway realistic would be too complicated, and I probably will keep using my bunch of ad-hoc heuristics to make decisions. I have way too many things that I want to do to spend the first couple years developing a planning algorithm rooted in psychological theory.

A thing I used to do that might be useful to start doing again is having some time in which I try to optimize what I’m doing. It could bootstrap into more conscious/mindful action.

2018-12-09 - Groundhog Life: a cute, but eventually frustrating game you can't win

Take-aways up front:

  • Yes, the game Groundhog Life can be won.
  • However, if you want to win it, you have to either design a system for playing JavaScript games that does not depends on energy from the Sun, or you have to apply some serious astroengineering, because it sure looks like, by default, the Sun is going to be pretty cold at the point when you will win.
  • The ending is not worth the effort.

So. The last couple weeks a lot of my free time went into playing the game Groundhog Life (I’m not linking it to save other addictive minds). It’s a game where each playthrough gives you a small bonus on future playthroughs. I have gotten to the point where I am obviously in the end game, but have been making no further progress with extra playthroughs.

I have not found anyone online who has finished the last version of the game. Only one person somewhere who claimed it was impossible to finish.

So. The frustrating thing is: the game does not tell you that it’s nigh impossible to win. It just keeps telling you to try again and again.

Because I noticed that I’m really unhappy with my time going into something like that, I spoiled it for myself. Obviously, spoilers ahead.

How to cheat

The game has a save/load feature. A save looks like this string:

N4IgJg9grgRgNgUwJIDsDGEC2CCCAXAGQQDcE4QAuUACwEsBzahAZzwFEAzDhNPW0tqQBOlAIwAGADQg4EAO4t2XHnwHCxUkHVYQhtNADUAhnCgtKAbQC6AX2looQoQhR4AIkYCelUMRNnKACZxQIBOAHZpTCMAD1pMKExKABZQgFY0yJBMWhR4xMpxOxAHJxc8AE0EIxEqED9TBEoMqNj8pIpRAGY0qNz2wuLS51cCWm4fev8mzq6u1riEju757P6lsSHHEcJxhAAVbQIICAAHSYaAzoWBztE+vI3O4pyUMdJmfYhjs-2hI3OdUuM3u2TaT1CkNCD1uoi2ZVGJ0BvmmzVB0UWBQoaXR6yxcOksno9AQtVA5T05goFlAiFI5GxURYzCMJMoIAq0AABPQIHguUYuSgEHIuQArCAwChcgDCbAA8iBpM5Tro8KT2cNygApSUyiCuIy5DXSEjlfVgEGaPjYVhGTCA0ShABsXQAHNIbYp7accGzqeF7mEulZCXsxHM7LSzQzetlmayZiAAEosapCNB0FD0LkEIzMUlcgDiUBQSpAKrVGooIBl23KXNTBZqmdlBrwRuFIlNpFcFpBgU98W9DrELvdQ9tHYdfpmFkDkmDoZk4dmXSjMhjzSZzBZ-o53N5-MFwtFEqlsoV5crQnVtRK9dcupg+sNxu7IDNfYglo0k5HjqhMk3T-naM7+vO9zOm6y5wKuKwbnSZDbvGu6JuyTbppmuQ5nmBZCMWpbXggqq3tWtaPvymEttQbZvl25Zfng-ZiIOIBemBgHAasHHTr6EELtBsHwZGkjRvSKG2nuSaclAPJ8gKQoiuKkrSnKirKiRVb3lqT56u2nYmp+vbMT+VqgXxY5dOI1rDpxs6WOEUhdMEwkTGuiFboyqHSRhaY0Thub5oWJZlpppF3uydYIlR-kZrRr4du+jEmSxnRsbxPpWTZFk+g5AbOa5YbuQhYmbhJ3lSehNbUfFgV4SFRHhdpUWUY2cWtolhkfkxaWiBldmWZ0bqhF0WSZeBc7OtCLmBG5IKieJyGVQm+61dh2a5kiXJ-ACXJuCQ+hNM1ZH3tFOztc28V0UlDE9uaZmsblo7DW6zrJM9-FTdCgSpPNEbrmVSGxjuvk1R1Wa4cFBGhcREXkedDbrQlBnJfd36-uln1iOEgTQZ9+UWM6vSiN0-0eUDXlxlVa0Q-V227ac+2HWgx0Vlpp2tTFl1YSj9FGb1j1Y+xg1ZZ0uOBANU55RBxOSM64Tk6VS0gz51UpnTm0NTDTXs-DZ1tcjN3dSlD2Y-12Pi-1PGi5NljvZIcwhsVC2AyrkmrUmyOBQAyngUBgJ4XIALK0E4ugIGAXI+3Q5wnZFNaI64PM0cbaPGWbA6W6IgbiHGE1ffbH1dKIaRK4t5XLdTnt+VdG24Qz-xMwdxBHXDLWJ4bENp3dGcY1nIvSy9OfiKEtlD4X1IO9Z4jl27leqzTXua1D+GEWFesdxR3NG116eC+bUsAWIxPWQTsvzBIZcuwDnkVdXaG03XkNbWcO1N8zres+3nOdzv3d717gfAeBcT44hthPQmrpJBuhgjfCm7sVqP2Xs-eq0N14-wTtvC6u9UZANSkLC2g9j6dHes6UEBcoHzC6M6Oed8q6g3Vt7LWjc9otzbvHBGXdn49wFgQw+2dXRugobbSeRNBwuVEHQym99GFP15mgtesNOEG3-jwwBfDM5PWIZxE+4gXLnymvcOYit4HKwXh7ZBtcFEsLfozT+HDN6-2wUjABeDNH920aAzomRgiGPtkGa+K4SoV2BpYsGGtUFa3QcopxWCk6xXUe4nq-CQGiLEDiJy-jqRpB+nnaRiCH4ROYQ3OxH92HfxUVzHBbj+YpK0cLbxpc84QIAoTXJMC4HBNdvQxeNdwZRNXo1DeN54ncN5rw+pnjGnpJ8eIUQzpskWA6TiApFikHFJXq-Jm9iKls1GVwtREyNFTNMgInRQ1RDJGmh9C5Ms5xpA9EBNZYSNlMK2drDBVS-41KSXU020yiFNOSCC-Ooj2mRECBIF5VM5EoJsaUnZ5SWb7I5mMo5qcTkArOWkieYhgIRCWWkRZLlTHdNvjIhhat5EBWiUo3WBzVG-OOck7FfUj66PSmkcQ41wUQTSIOCIMLZHUvhbSxF782EoswYc5lmLWXoxxV42Z-VUjQjuXbHJg4RrCqpUvax4qgr0pGWi2Vri-m3Q8UqmZeL0qgqJRIoJcEQnz1eUU95gzo7+0DiHMOQgI5RxjrQOOcSzXJ1wf8xV7Ls5OnCGCyB-KpBhCdSJV1sLRUGrqrYpFUqv6ov1tU81LLI192tUClVTo-EarEdyxcyRZ5mNCem-VAyEVeoDkHUO4dnCBtjjKplRb5UluAcq21pN5mLOrYTZIHpnS0MbWmkVLbIltoAKooByN2rkOAUBYBMN4b5Ljw21Mtac6N1bKBAUJVOiCILJBkudT0ylfSrGtsNT8HNzdpWHoSSna6WKo2EI5UNICbpgP3MsMkahmRdUvs2Z69dm7-UER3XuuAB7Q0DuPRak2gHzneNGi6JZUHFyBlg+Ej1bau3IZDkYPAd4dpMF0BhxlhbsPFtPWyoDls3RpBIzeucwFJBXK6Y+ilhS4WZvrlyVAHw+D0Dowgbdu7ojof7WxxJHHcOlvPd48ILpeUJrnF0GaIRyNvJpVmiVuzv2YY03+zqCqdPcYvRQfTUKlkmcXMS8z7rLPSc+bE1jPzB3-qcyOm1JDwi8fA5qiwXnRBugfam3pFH-Mvz9h2313bI7Rz7T+8ZQ7ON4dxVFsDtzKEQQS7k3zkm31We2ZKr9eb1MhfY0V7TEXy22ui6XTz0Jmm1YzfVgLMSGWmqw5pjr+9UmjrK6PfrwmQVDeXSU9tPrqMBry8G1rR6ptheHbNyLnLwjhHIYtl0K3+krsNYhv1uhlNoZYxN+zEbivOfw7Ms7b1FtQqu6+m7DXZOKAYIpx7qnnsFra-txzh2GndaiyXCrfLjMeiuf9+DVH7sEWDnRhjhwEDMd27+t7nWjsI5O9ZZHRnLATmSBjyjhrgesFB+qcH+7ieFYO+9rrsXAS40S55yFbpnbkoQesvzYqGubZx3jwsBOicFYxdzsn8O+eUEDEJgTtPIXiHnWL8xbq6uA+k8z+TYPUMQ858r2HPPyfq7c90ERNPqRjWE5dhdqWLNS+kzL2j9H5dMaEJDreJOT2q8BQ7wMgRWn2Sq5ERLomUvPrSz7l+ZvWdKctxzpXcqVczbV5bJy9ahfCfyZ7lP3upMvw8EIAA1v7hjPs0BGBQHkbM1u8+24j2Wh3zp9Eem167j6Tok8uq95L6vvtvVBx9nX2gcA4DME76F7vBfI+W375LTzI+wMM-S4FYOkdaAdj4AaFf7X8-4ML65x5yQ+eEy6B9OaFeJPDZNxlmf0d5+L+X7n1ffMduN+3ixKY8nm8wUKKa4+lek+I2L8R+YAJ+dGtA5+-+l+a+1+G+t+ro6qlWxml870++Mkh4CkJ4yk54akV4h6ukeAz4AGH25krmyQTkD+VWhUL+BuTaS612sk8kx4SkZ4qkl4GkdmNYNBdB4W5O48JC1y4Q1ObSbBi4zyr+EuxuvBR4ikp4KkF4eYmAMAYAgoModACAHAu24h+kcOgK0hnK1y00nmSaOqKhRu7+6hpBAh2hlBIhwWD4MUEhlhZa1hQ09aIuSyYQ8sY+T6b+y6rh-BWhFBQUehBhsoxhph1BlEfhQBVhls9acaoR0I-eRBU+m0mWPqc+C+S+F+MOgBPeumsyJm6QoRHoT+UBkRqh7+a2AACv6vQP8JgK8PQJUQ5tUevr3pbCZguEPhYIEE0X9k4c2tdmtiUbPj-hUWgVUZMlxp9rau6CNI0YuCZoUTWDEZoeQUIepGYekRYZkQEWMTFnscEBwWJuLs4dESQbEacTofaPoYYSkRcb4VcTUYQoEWLO6E-nsYlvTnMdwQDscWQYIReOcWkf8S+JIfDsCS9GNLxuCT0IcQeHJBoXCR4Qkd8ckbQCYX8TsBkYCebOiYCGNM6KwXONMcJv1LibCe4fEboSSc3mSa4LQKwBSTqACSMX1LSZQGNJkOCTymyW8ScfCZ4YKXpCif4aKWMXIfIXHkyU8pCZwYunqjwbKYSZyV8UkTyeUPyXgIqbQcKZgTca5mNDQnsW9DKfiW4XEWcVQaIT4ZSTaVaqqfabjBqXxITMyXIS6XwXKUSVyaaWgLyXwAKUiT6cqdcf6d4mNNvpMaGY8cnlEQaa6e8fKcSUkbtMaPmlvOYcmdSYwWmZrnsYQVCfqTCYaRyUIXmDANHFAKcKSK3MwLoFaVSSKUCWqRIHWQ2rqRPmoc2e6ReD7C4CgQRGaXyQmV6RWfQV1mKRQGNHrnsT5g2XBurOydOdKIufGZaYmUKZWYOTSWqfMjuVInuanuyIeR8dKNqKWPOdHLGeacud4auaiVkfadNIPngZYMyTOuGQSS2Z8e2TgLuBaa3meSuZcZebaamXUdNJOiBdSGBfrk8YbvMU2fmZGcae2TKIgK3kZL+chWuVIWMdNPGgoVqZIMkC0eJm0atlsggUgWfialDntkMRsSVnNpyjQnxnsTqXhVwY2Zjoaksd-uUX-l6WHjhleaViJWkGCZmZCn9A+VXnAYFEWAgPRtPlAFwPtAaGWc4spVpqpcJUNE-qNKEbrhEWxS8QsVsnJWUb-oMaTrZcdvZUjk5UobiWtlxafigbxaHlzhgX6S5mmVCrHsGRBHjEoaLpJXqfuQfsUV-l5asUpdFcMahXFXUeIGBqEYsgstmdAbmQDqFcfuFagflTboVbFVsSQtZJKZmRVWNCFR8tUJaEIMwPlk1V3i1WesVdsQPuVSyS5c8QRTJQ1jgHALyHoHgNQJgIpd4dZdNkVW1SJfos7oxaBRVaTL1Z6j7BABwHgHIDUFnnVOqLwI4JZeiqNYJQwXZWLGEP3tNfWmdW2gAIpQAIWJAhw8DUCt76CbUvbQ4CU0XAGzJhCBCGZHXYWLLJbVXsXuWephXIGNVbUFVvW86WzTEhGZm9AuSzX4XQkLXSaeUrFQ18XbVX6tVqVDRI05Rk1LasVzXU2M4NZdEQA9H2j9E+Xh5+UU5s3QTAUo6gUkxzB-WGpLUrUn7rUM1RXNWE327E3QS0khkkyBDc1U3SV82005X02i0qW7Ws2fXvSJUQbYW9CwIK3S71W42RVWUE1w1YHeJ4xOihG9D1njkwHG6LGXXXW3Xbr3UqBPUW02VW0fUvQG27Gc1P7O3SZK26Aq0bWx07Us0J2AgG1zr+0slp0vwC1C19E4Q53M3jV7Vs18a4Ey3YXFw1a6WwEf6+xh03XOCR3YQPX+zODV0xW13W2J0aXS0u5THFzgWe62D2CUSoAYDYBYpUDwhJkr3ADFCyBnB4BNw+Bb14AAD6JhHA+gvJaA3gdQdAjAignA3AvA-ACAgg1Y4gAAdHrknREN0KPBpf1LeTIPILfcoA-WoC-dINoHgJnYYNMMvtSHPVoACKcMaLuJMNfUwKwHfSoI-c-bUGxLIAoBg8A6oE-eoBQJoBA1A8YI0LA9YMUEwCYGtagwwOg0oPfcQzg80K-fUVCDw7w3GPg0A2w9g6Q2-eICxeAxaZQzA5YPAy4KSPQJfTQMw4I1g6A7UDiM6K-cTGI6kFCklqkIPgI4Q0I2o4UBIzoHoNA9QzI3Q4g8g8wGwF2Ao8HD+PveA9UHAGtY4-I54C42AG4yAAWH4wEzAMFAAOq6B14AAapwHRpIAAEtAEIH7HRkwzfcY6oyQ9WMEG9IEO-W6KVcBP3l-asEY6w5kxw2Q+Y5A5Y1Q2YDQ-A6EwWMjDE3E0IIk44Ck5aVfcoxkyA1k+ozHtMa-YGKEL9NBMTA7AAwQ+U-05U+Q5I7U9I3A8UOeAALSnAUWTC7p8Cn2RyUAcAmAFjSAFiIC8D7MUCHNL4ICmgxCnBwCGT+OXNHMIDFDOBGCIHZgbNbN1A7PjBklPNXPHOBNkAqAXNAs3Ofh3MPPGiAsvNvMQzfPCjbN8j-PgsvMnOgvnNPO71mC3P3OPMHPwvSAACOZgZgSLMwoAfzezcL1zmLZz6odLwLCA0LhLzz1zW9RgMAlLKLuzALRL9LILjL6LQrrLBLsLlAuLrz0g3dvLvzqLtLgrwLpzYLOLQgeLULErwozLMrADO9Tc8r1LirArHLKrWLTLyrkL4rMLOrVrXLiRRgRrIANLprELDLarVr+LtrorBYtjpwSDwou4zrrrvrkLqr2LXrWrPrurdDHja1IbJrYbHrkbZr1rbLkrabdD0AzAOEib-Lybwrnrab3r7LELxQMAJwrAzA+baLurKblrFA0rpbmb5bLsrAngiAtbSrTbGr4bFrhbNr7L0rxQTE3bprzbRbqb7r0bZbxLILxl2YNbmzyLCrBb9bU7jbk7Q7rb87deCAngMAuQnz9Ay7Pzxr67UbEbjbM7O7drWb0g3L0AeA47hb17g7Gb97bbIApwegfgF9r7G777G7d7YbxQfITAQggHV7A76rmroHsb0gPR0AKAYA1Agt0Q9eRl0HJbm7H72rYHj72EZo2ArgOHM7wHUrfbLbX787RI5HGLeHIHn7hH3SazzAiQmHngDHQrlHuHCH9r0gEojgKAJgPH5rIrzHBHcHerNByMG9xQngUA9AiAogkwRg-TgnIASnKnCAogh9dzh9XZQgh96HjgaTLDmDczpDBTcaCyY0r9b049SWeDgDfT7DIj1TUj1jKz0gOnqnBnpwRnpIpnSTh9TTVLinynqn4rpI59VLIAdz+KaQr9LFBTpM70+iTkbotyrypM0gv7h0ObRAFU9ak6aDigJXZAlTEg-GFXrAVXcAhw-JH6ZjawKAHgngnw3wMYEg4gQQeMbErwnX3XjXEgQQhISIjMwcUAnjwacE1YsCr9wQ+i5C3QDJYzjl7XI3XwjXMjhIMYzAqYGnTATztDfn0XensXlI6ACAh9yHpYaHgtAAYhpzU10xZyo9Z9WBIF0K-eqmU1Zx5z9150sz5+d9p5d6INd-F-d-6o9+h-QK97wLoME6vRd7p9D3c3Fy4KzIfZ45gK4+j5D5jzD7j3d3c6cAYYo1oL07M8D7UH-ZCNMU5OEFw6kHIaCID0Q8I2A7TxY-oHU1SBD-51d9jzd3j3c2Z0IIENTwE6L6ILkGgKcPE59+57z4z5oNzyYwM21xQ2D-UzYxj6p+eI12j5vcbwgIEOp5pw+yT4gIEIF8FyZ9L2r-TxrykMBAbXIW-ekIllctudM19wz3r4s4L8syL5d474Z8Z6F44OF8FPL1H2T7d5MElxQPfm6Mt9csIuqcEDsaU15COT+84K3MV0X7WrT+k4QDGDVzZAs9X41818wK11U9t14KN71zZGIIPsNx37t13+KZN78E3DN3N-c2Seoylzga6BkPMjQiZpOn311wPxVNYAd-SEd9UJmBc5H7p4ECn3jw96h4j8j+96fm70Dx750P-drxU6Q6CPr+H+D-A6Lwf+L7D8f090j296j0Txb-byt6H87uBPf-lF337ADAuVPLwJfx56mMKAc6UmNymggpdfaT+cIKUzc7u94BCzAXlY0N6+dAB7-YzrDyl5JNZeMA4nm-yV4q9YBOvSpkBD+6QhEsAqMRgKlZ6TcZmV-eAcXyf74Dher-KPqbxjDm9wBiALoDb2IZadReXQJ3rH1d49Nq+3A3XpuX6gaVggbPaaHGn7wTgg+6vHAaD2f4EC9+4guQSF2l4J8CwSfXTl0GAFp9AQDJX3nGndA4grkksfGOsmL6Fcy+UAFvkXwb4sNGudfDmvVxr70hm+rfTQMv0770g+uA3MIu3xX49dYh-XDPsP1ODTdZufACftWBnRaMbI1kONC6BnSSx1U0Q1fstHX4Lwt+J3XfoIJsGQCv+p-X-skwv6KDLOcAlQRIC55YDlBNXQwfwIaZiCEAtgj-uTzh4odv+Z-P-k8wAEyDIBoA2YcMNGEkDxhlPOXu0OD7X8c+SNCWFnznQ5drkjpPQdgJUG4CamRggQcsMgFkDHAFAxRssJoGq9Nh+groQdUc5vRhE+iGhHjH4x39vumvAYULyGGW8ugwg+kKIMt7JBJBj9aQZd2SBmCXeSTOgff2rAuRUgs0PJsGDzjkIY8nArYQYP54XDBhRvQAQiJj7mCwuEXawYgGSB2C6g6fZgo8i4buCVgcwZgngyL5sRvBKBXwXtxv4SNG+tfB-vX0FGBCYwEQpEG13KHJCyAcQigJLBzgPAdusouAON28jb0Mho-LIfN0n7NA36chYmLVyGalx6Syo-vqqP27VDjuO-M7vUNpGND4eJ-F7i0I+4vDThdfHoVwM6H9CiR3nYwfaIQB0ixht3CYQjxdEo8hAkIskQsLwCE8lhUIm4QGw2FKMlBPo0htcn6gRAQUbPGhKEF4zQRMB3o+gZ5z9EG8rhiYkMZL1ODS97hNIoMU8JREAjWIPKLRmdlxjTREsBtPrCcL6EiigREfQMckHBFkBoxovNIDCNIBwjdOaQREXHzJBV8OhJYtEd0FOzEoUuOIXjGBnISTp-hIfNvnwOBGkjxxc4iwdSKoGXc0g9I0AOn1Lhzp361kd6DOn0x8YxKngzQDyPL4VReBdPIIaQzGa3JQhTfI4FKLb4yixu3fBUcEFuTgTB+CA9IZkPH4Ldag1yNsXxlNHEwCx6QJfrkBVH8iqhwMGobaOPGXjHRkw5oZGLdGpilxqI2oKNFS74jXhvow8YOOGFXiqxd3JoRGJqZjjSJHE-HnGLAGW92Jqw0MesMoHUSCRKg5gvMnrQCo-uPQJ-MmkYkejSxLEl-mxKTG1iUxbExse6L7E-c+MmjEILjA0ougXQu43oemJ+7nD-RFYwAWkBHFwBeJunZ0JOJmDftRezoU8ciP0nWTcGC-POPRKuQZBRoHgvcdf1snliQRgA7yRSKRHx9zxcwy7s6GvGJdAQ3KLPiLmcHRZ5kf9YlBv2WheDS+vIvwd+ICGVdhR1YJyI-1-ESiQJZwaUbhItEQTUhCVHCR1xalwTDGU3bUUhL1EZ9RAy3U7KBjn4ditcsEtfrBEO42jTuJE1yWRPDE-9KJbQySUxNIaBhX6XoqScxLD4kjCBXkxac6OWk8ShJsU2MfGPrGpT+J4kmnqEIMm1An8hw9qal1Owi4FYKkh6aHzwFHiDpKUrSeQJ0mW9nQektaapOyYB936EgBkgbXZG5crJy4wEWWMuExSvJTklyYgHCDuTpxmMnyeZz8mIygg-UaYt0FCCv1QpPKHoFtwimEj1JAY4YeEDxkmckpDMtKenxfF5MQgeuJHAKm6CGN-BBXEqV+KKkVSGuVU2oE5FFlhCyAkoxqWBOalJDWpA3YvpNLlGpD8u+rLUQCDH7ZDkJ4pNnswTnShB-eIQFitAkSExDKh00zfrNLqGsz+JXEk6boComLidpG07aetJB7Iz9pJghAOECOlTCWhGMv2RdLOmi9-ZN05MRJNdmezHpiWPXGBmNnv1+8pMUaEWLdl886Z9k8OQDLuFAzAB4QUGTHPBmPS5gnMx8bPwZKkzLJxY2iX+G9m-TfZ4QdGWHMu5uhsZdvUXm6CZlNj9x7U9AUNKfzMEORpVT6f5O+nEjG5gY7ufFPnGWDIulvN0GzMBAFMcQKXHOLlJWDBFCpDIDWZ+L5ECzi5f46sFLTFGVTwhDUwEFEIVmWy1RkEg2v-VVl3yMkCEvqbrIGk0J8miAnlLkj67Uwb5FQhkARJmnb85pf03TkvIdlOjA5K01JgTLrkICyZPU2uc2OuANzWJi8gORRNOkJjABkC0SXj0WH1j8FOPMSVHLul08vpm5Fbi6HmR5MS4RkvEb2PHkHi9pU84YSQol4U8axgMiSRwqLn3SWFjyONFtOixI5eMo8KZjTLeEDiNJi8lubgtF6hAO5nky7qEB7nwLUF-vMeEjSGlfUTMjyICGPMJmsKfpGCwAeotnlnjE+F43TqEGXmUARcqEkICFKTrcyd59c-eWVOWi4wz5Ys+kJUwZKrAgJ9UlrqBOvmdTFZXfNqbkl74ALVR6og2q-O1k6ichj05ICM1yQaUoM9fdgeaKiVTSd5REsBb7PsVQLyJ3E52atOLlULXQXDYxQgtqlmK5FFirBZUqjGty7FocxRWoqTHQCKFaYkxUjQNqZT8xy3TIHOg0YNLUFUUlGfNMQBlKCF3C7SXwst6hABFlClhRIDGaczPh7oK5BgKITSK6+si+mWsoUX1j1RoAN7rCN7ZmBhhEgDRWDKoW5IoUIQBzsIgZLRZ8x0y-cbMp9mBjHlViqkTYuSmY9xADix3PfhCCaMjZYGRSVzyL6wJBZRXA+d+OuR+LpZcASprxlqlCiL5YSuWRErwnRLKAHgp+YkqyCajEJ786sC6HJnExWBvGJSRpSyBPyrRhE22XaIeUQrylS06Ya0LgXPKWFb0Lab8uv5NLJ55ihXryqWVhjjpAq4ORIG6WXLZVpC6sf0t7nX8ksfGAprxnXk5cMBWuY5WpLYXSqoeaqrhYFxWUPDLeEgDZYMoQVQpUgQ0hWEbL1w2QMgyCjOUjKzmoyLVFy2xYgACbkUBqQ1YNGpzqBL17mRlQtgaGO4nsxgApXDl6CIBXUNAmgTOvQFyAmB9gw4NNd0z66aQPmOEJNXgA6IQBc2PFNrhxH1AOhEAjbIoAdw+akhw1pwfTnIEibitD6l04nqGtbWxxreUarADGpvaMd41-VUtRaSjapqTChakvCACzU5qmu+audfik0DvNE1FpCtVWoio1q7Ida0dRcybWbgW1g1QdYfU7VYdDOvagAf2vPXBoJBw6+tbGo3YTqS12YMtTOtXXpqb+mavQNmtE4rrsABajNcWq3WsAd1J+PdW31rUjqG1x6rev1QHWPrL1Xam9WdPvVtroRz6o9W+pQAJqp1yamdrOt-VOh-1DAZdXmpA1rrOgYBdmB+voBlqoN1a2DQevg2vrBgzasNbHARFXr92GG3BVhtjgTjcNCG-DYRs-XTqU1P67pjPGkBLqgN1GhAKBs3Ic1N1RG8tZWug3n42NtoQ9eJq42nqeNwaWcfxu7W3rigt1IwPj2Q0PrkQIAG5VOLt7WbbNZ6ttU8pqVbLXlK3YMOTLXnMFvVscieXZJimubhNwaJmfPICbha7NbayFb92ggZLXQksx5NDML6lcEhXi-kUlnK51SAlD-QMHivFEEqW+4S-JbfPlEZkKVqQzASPxSX9TsmDJLRjHhBTuh3lSNMofEvwnWyyAxSu2Y+3eZuaTNXZPlQqtdHVLBFJinOHkw9klyxApy+ybFvc2xw2lTsjpbguW0jaVVxPLbShtG1yrbpWq+ATHgLGyFDlIzAPr9HFW0yzVLSvbfZtzky985EWoLs4Gfi2b6QPas6TAEwCRrrltvb9r9v07Ar8Zwqkxbo0DACoyZ7oJyMSiSXMKTF-y9hdIGB1RaWZqOv7ZCsRrky3okIYRGM3mRAR+Gh87LYfJCUFabJVaCnTLMvlNTIllW++f-IZ2AL1RPQ+racB1m6jqwfGfIekAeLGyDhbK7rV5GAU2zQFA2kAMDrW0CqXZU2xpfohu1dDFtMU6XWNpgU4KQmWO-iUQuJ5q7Dt5C47SoIwFgZMkeQ96IRiRpK75mKu0kfrvVXLLeFtqqXX9odU0StFZMnMdbENnGyrdiOhBXGD9V26-tgagAb9qHUA6pBdvcPZ5vl2oKoULoQ1W-SyWJ6xF1u01c0rOUu7o+QXeQSCqsF67MAxAh3fYOaDEpHO40sRu6A0GciKo6qMneVMxXHz1GIQ-LbTsJVXyKtrOyCRIAmI1aJumsmldzselkz9M6ZYmOkHmT6YYJIuwpdaIl3crMdxeq1Y7Nl2TbNlJinEOnq9lB7CB4emXUHJ+1F6dtYe4-ZHM1WaL9xLkQXaPBzgjMNus0eGSgr+W2699Z+g3Taq12BA3dPqoma9J-rQRJYv8nEdvvUb-czs8OwPXdqz3h7Q9FbTAE+sj23KgdCB2PRvsaXDzIQeQznhPuYGgGQt0U4PbINB3MzQV8BlYSXoZGd71kH4oWWipFlZAad2K0hsgKb2hKytRKrvQksgkL8hus+tWSkEskc6udaS8Unk2YImZmCmuUeMGC4M9ailXKogwftgXdNwdAe11fgbQW76Iev2igyvugXYKZhWuvQ7D112n6TDaww3Zfuv6KiChJmfYWlwliaHkd5i3Q09rrGF6ugP+4LQqKz4CotBwiGhKTDCBBb5tbmf7l9R1Wv6dDCBuA5jpw1IHnNKB8kbnspFg6vNJi4RLAlZVaM7x+iX6KEaoUuGWlv2lI87znkY6XdwYpZaXrb6vJaDqK7xQyClnN79RbEJg7LOoM1bUhwEApnIbgm4wqVvUhrbSoCkta9GKAuQtZHcH9G59nKhfcHuqMO75VGuqpUKoyPqHlumhyVaFsWPKHNdhepY1arMPwGjjpAqw2oa0XdADa1yMRuMpjwSAUq-umZdEcaaYAzjlhz-Yce8NhH785MuSfpiNVAH3o-DBGQrteOnG4jLu0TYkY8nztfts4kg0bsCVpyTMb9J0DiDCBrjnDEJzHYidSMJTSDBe0-SJMoM3jqD9RlFT4KaOh98V1XFg63rpNNc6d8slndwZ6NlzZjAhzciXC17DHOdqSvWXRq2mky1xEgJLDZDiVsn5D8+2oYvuhP7G1jqhjY6gq33PH9xOxwg2-tJP6GKl626MQiZP3wGdT5xi-Zcf3HpARoJQvJoAbGj5in9v+0xVKpKOYATTnxp3VrrSA-GqFTkXHXGl+iBgfevi9UxKuKMwHXTUJ37W5LqBOa4TnLTHXFIJPzjkTpDB+QbTxgV61x0xKRWCZePoKXTiZ8o9YuJPwHrpNRqg210pMl9Gj-Ilo+LKCB9Gj57ByIVybvk9GktrZ9UXMBAiD635w+1iOz2JiGjJYYpvg9KdF29al8iht-WWeWOr6Jt6xuPX3IB65mNTuJl3bOd1P8rD9uCqM0aYTN9KUxKpvua6DcEgpUuEQfnRgKGPP7Ip65vc5HK+On6QZ6AWgdYZ4GJZluIUpyFXJ5TpBQTt5ngWGfslRnIzmALGTGcB3wnwLaBx1agp-Oeq2xCsM2RkBvOOngLqumCyQei2F6I55Z8k5Wa8gNHqTtZtg5TsZ4JCOjLJ4lV1JSGpDiUpNfvTyb9q9mRj-Z8IyChHikxE5xs0mLkQtmAKOVICuU8HrwtzmDD7SuXega0VMDtj958C4qY21a6xLxxwSbuYUvn6jzS50M5kBFyfn3QkIPOJzxxP5nwzKl840+fgOFzXzzw80zYfmQMq9cDJU8yOZ5TbGMLolsC+3MgtR6UDM8pMwoLsvwDfE0WFLnZyAg5M-dJqzOdAZAuYB-LRZ-PQvJd2cL4utRrXkRapOlTSLTZ8i80Dy1MnOj9OklXRcoAoBZucATs7VrmB8nhDgpgacZOJkcjS4M6K5ERgEuWi4GChhY2-tSvjD5zKhlMyfK0ZyXTLcVvq6GIGsHHT9E1whWpa12zXuFZp489qseSSwTMjnNVLNDzgmXtDbxxa9ao9OF63Q3plhU-k0bEpTsRl0aL9AR3RXfVsVzC26DAvKKfLyB6C5YoCu+SgrKgvGCZhjzv0QUroGhBPt2uPXg9n1xK4lLIOY7FlZJ9KYRYqjEXsrmV3K-SdyF1nStLZjq0rIoDlXF8VV8Uj0FqtayBTjWsA8MpGi-RLrnq+iq2aEvi6RLb+uG1ufG2DX3zKggC46c1NzLmbilg05gBZumH5rheoW5YeWvaX4BBikFKhP52jwQUUV1c3ebGuYWxbZCyy7DdOsmKUtW06aOkGZ65IgINc7mx5eZuRnSwuOVgK2oCZgB21Ki+drbZB1fX0jkt36zIYyAZBHOf54CKkGNs+HTbEPR2+jphvgB21kKjK43urMkWi+7Vpg5UxYJkX29HBro-wbbNBATEhNjPu1epV9nRDm5NnkM0eSjwcRt11YOyq6uyniJhAx24paktwX9xm01zoBeV0q3SRNd9XYYaUvE927cqk49IB7vLGjtHNypgnsDAi4eg-3ce7xjQv+31zA9q1bcOe2rLQ7ivGy0NcZ79QoZOxGdHmJoTMF3Lc99tVCdtsR7HNUF+M6HZz1Q2FxrtmrjdbH15Np7uMJLGdjBuZ77JJ94OyWf7unBl9aVis9iFEYmioM70aLMIgxWeDbkDekWYneYPVTGTJWpO9je6Pp25YONuCRz2SVk3Rj4pIaZIoVi2cx4jyMDGOZKtWzurTNwO7-drvr7671-CYvdYW2t3q71Dju+0ujEn39zl9w89HNvupmQgjA5NO-T1ylxICb9501ns4ePmjrAAk+1rcaVXJHOjA4CGwKhRPiD7zDqh4EGPunBEDZ93yw7d0ewX3dGpyWUPKYHojgbM9sIwHfga23iDztok8lfsfY6zsmjSWETt+E+8orRfUENA93mY30bEshB+fKQflb0HpVhUbYUzsGMsHIhoU8M27PjoZDY8He-TYrvzHKHdj3RzQ8XPSWG7c2qhTzYBXFAXHbD-U2dLKe92RbsjnJ5pd4f5OJVoVoI+QmW5jwnODp2e5o+ycWH1bMj0p7o-kdaLggIzPGOhNHhgZDlTdk24fbBGSgzelT04Akf0fvWL7ttso3npduNOeBqQe-FBn2H63mixwxh06d2MsONnaRpxzbaWcJby9fXb+doLkIeKBRUdlG5HbjukNJlsDoq6ybIdp2FREymJ5CDif1WmtUM261CkRqGKnj5dsXX1unNUOPjk1iS+trrsmPr+CscmaNb2sDOkXR-FF4qsWd4uQBNT3Fzw4GXoueBDF7CXri4aUz+oOZ5uzbu6dkvpHec5e+s6GcamS4WjJ2PWlGiySDEIZoC4feHHzORBizmEys6SOGP8T199exkl0U8ohphtrA+5nEdnOqHcrzZ1c+7unA3TqfAB90E3Fe3VUttBki0E8F+O6DNJl5x8550hP-FYTzgxE7VltS3ouIccykLaMgvybQQNngshFwZAn8PQU7ArGF1evyHldkpdk4Nf4u9Ta+vJ3Q+CuFOtlh9uN5xIJc7nrnGbgSZZp-u5uh7P1mrjoOuTdiRmUIFikK5Oe2OBnhbnhey+d222vTa94ew-1SAV7QCb0MRs4MVtMv+xLLgtzo+jOwmtOttwszq4VedBAt1Nv7sXkljTEmFNbw+xO8uc4Xanm5-+wRfFgCoMlkIbQadsKa16YHrz4WQE9geVNuUUBwq9Raqu1abIpD2i9ye5RDG6rfrhUZo0qrWQXI-eaCDoo6l-OGb8Lnq1Q83f9Ws37N4tywZVfYvwbLDsD8i4TfZu9XCHua-m9DuoelrWl7Z10IyCQEzsf3K03MBdBc2unOLn+5h8OuNvrnL55XrZZWs8D0gwj6CActAzBBU3022txR50cQXR3dvW24zKRNtufuZXfTJCC4auhuIHSYV2cMPuCfHH67gZ+ZfJ61HJDpMd+tyjEYWSgKzz4qTWa8ha57XLewJ8yY73FWn3-z5NGXdTvqjMgdW0m-E4GkZnfoRwwMysAYvWfI3QCyc-1vlMCfcnypvhzzo4+NK5P-NxZ8p9DF93Q7kXjVdh+TddCpDpM+iQwpy59v0LYXtl0vabenBrLdHqd9MQyVZL7832dsdoI0fkeYvOj7y3x+-a22Erk74TxRZr24xHOGlUqkBFfsyfmXlX+r1-ecenBFrtR393ot5PP2zs1yXLqTptf8jDPbeuB8E5M8-OaLBSt10EHx2Z3Mgr7hz6C9wZ7uCHdpiQ9PuvSwufPCL7JwdamtKmp3DDpWzwMPuXeIP01gZwdei-1fyXU7-qLn1dDvR-umQKDA0W68Z6JHH9wb+4fzn1euX2wsDCyLCBtaX7nwir3B6ofPXxXEIxZ69dq+GPIbjXqDzzsLpnY8Ha4nccnWXeDvQ7OPtd5Udttq3v4ADqmziC2n34gKQSoxe+Kytnvmg7R+b5UxyLfPb3rr-5yG89d-PbPwL1i9g-YsjOIXpVBZKq88+AeMnwlqu1Q9p+ZukPkHhj9JKGnWOinh9tXysc7scPTgBvt7yb4+9NfmgIKdp9yjbESGcuhRlhVx4p-g+OXJvqH-AIKaEeULvGXRqG6R-v2YpNPnR1culdxm-WP9oFY44K8TOWB+Qn3kOY1damqHUf6+4p8j+Wqt3CNnxMTuMlJeWKBf3T8jc5-52L3pDB0vz7M+-OLPVWshJncma+ucHPiVLuMwKajQWCSWHLuk7hdTmQP2T5VeU8TeBecPNXLPtM58PFOUdK9zP+B41-PeM-XDx2zP7IUS2R-5fq5JiUUfE2IgOINy0D5iuB+277a5f9WI1vT+PfXQnYtn0G7cpejgPk5z+MP8sOJAx9moHXiM4PN1QRgKADFpAYn5PAPsIgAkQv-qoD-+gAQgAkQYAI4Bu0n3naaaGHjuuZOaYAUAGnAbgNAE8UAtDEA08wICkCNmGILCBwB7XLcAnqSAXgCeAETPXggB-AP-4UBdeFAH-ArGnj50SHNGT6VepAeQGRMaAQwERUmAdgGogYEuCBYgY8BErEBVmn-5kByMFQGtwEgRDD0BMAZb5-qK5v24H+IPmFriBngMjBcBbtLwEXA-ASNBlCggcsA2QXWo8BYgJAeoFsAQqmIGgBZAZYF4AcgYwFa+o-nybKBtQM77sBbADECkgsZN-bSu--p4HeB-JJHDoBMGkwGVmd3rJ7k+HgV4EZgQQVoEYB-qFgG6BjQNKKGB9OqIFEcNgZ4BGEEcLAwAC7ATkHvaDgaEFOB5fiwERBPXsj7wM7AYAEac8+B3i7a6gbUFoA9QfQDFBummEFROLgehbCO4zDNo2QgZkbJlciAeoHPczgAcDDgUgf-5jBEAcprtBZYAoH62W0mNA5w+7lBhXwmhmsy9Gy3IqIMkOqiEDKSUQaMHjBymvEE8BiQXwEpBZDBp4N0CsCXBjMCsK1owSaQRQBLBq4qsHZivJszq3AazGEBky+YuiLR4tnHxjFAp7GAD-aJQBxpjqQrO+oQa3TCRqyaKQBRqAauaoiEZ8G6pOpSakGtpqsa1hAZqcaZDKCHMA4IYfTMADzC0E4Q32rgpghp9tGqGauHLCGaa36jRq-q31IuoAaVGmiFshGmliFaau6rpp4hUIYhpIcxIY7zngx9PxLoeYIXo50hBITOyMhvIcyEqatGn-QKaHIUppohqoQxpwhLGjBqChL6o2pEhYALILihkAuh6uaJIIuz0ApIf7BcAh9JACrsWPhfYWhRlHwDZgNoaZQcA9oRZTGOjpuqTcoToDy7fYpQo75I6iAUNqWhbodaGsAnod6HCg-XjFoRhroZSExhdoQ6EQBHErUZ8yHjmzwkO1sPLYk698Gqb+OZesVqhOC3mIAb+lfsnbmeq3kL4rejOkw452bFnnaJ4gNqloy2HtsiqC+QHr35ZOVmkmFWhHoWmEWUAXp96lw9Svv6M84YdUD3cyYe6GphXoemHhem2oOFRhw4UuGjhOuqS6Das4ZGEphtoZuHCgFvp0GkwpcJiYiOvvIRinYSfrzYQ8LoUOGLhcYRmEf6-TiKFgAh9O9q8wn2mQBUhiYbOExhgcKSHm0b1jK7OhQ2oBGeAwEQpS+hPhmM4T6rHpdqta-FqwFVBA4QBEz40Eb-gJhu2hBGYRzAPTQJaeuHxj34Q0lfAPBGWkVIbBp7vQYBOapkZ5jg12mjameNYdX51h8oj2JMW7Ojt7vuJXqlzjE6EkEYdUzOor49+vnqSKuakEVhHXMg-gubD+CXnfZ-cnTmEaT+5ipJH4RhEbJGRi0YupEdo0kQWDbh5oXhF6RBEQpQnhpQWiL5ibAthKbS7yppSoRT-veHGRQEaZG-4rvs7pSRrkUvifhEMD+FwAf4bhGzh5VrvQ6aCwU6ER+jmkNrBRq1BFSwRYRrDLCBFcstwgmYUreElOu4TZrRRoUThH5BUUVAAhRPFNjpluIJqIzy2LFAKhF+LFiWE38VyGX4-cwgdWHIONnj3omBovm1KN+7Fl7xM+skmo5OKFUT2FK+jNir7VBeUQVERUY4QoFOgIXloozhmUflExRFlFpHz+kUUFHzRoUVw6uaWUYVH1OFLo6btaJXojRnYW0hEBlUU4QQZ3hI0atFjRi0a+HUexPFtGxRX4TRB+RAUQAKnMp9A6D+opAKRyqGxQBwAnAYAPqDVsbTJ1xoujppp7lBrgedHpRIAP9E-gZLCYD-+U7spFFG65rmwvqGABACtBkwHxwzs1PMwA4AtvEjRvQgMIEzxAMapjGtBh9F6ABM6MRTEnAVMRgDJqb0eTFnMDMZSEIxcEGQEBMhzKwBwxswkxxRs+MYTFR6XFm6B-R+YHgD8x1MZMHE8vMVLEAxh9EzG-R0gPLHSxnMUjHE8zgPQCzcLYOzENBoALjGMcwsbbwgoIjgiw6xDzBmD6x1oTTFaxCAJbF6xWMZSHKxATNrG6x1sc7HuhGsdzFBqPAD6C+COMbBxCxHfCLG3KyFjHjDCLeA6C+CMsdgD1i0cacCxxrsX7GJxscT7HO6hzOgCeAlMVXR1ARsUKwmxosWwIgoEsdnG5x7oXbEACWcRfQVx1oSnHVxreLXE2xh9BnEBMxnL2RAaRhOST5xwcbhxFxtyjb7ixBXK2oGgJgN3FehVccUAdxY8XAATxSsZWoqxP7KPFdxTAF6FtxxPGtTjBdoJ7F14QcZJwhxXXGHHOaD8p17FAW8RAE7xlMXHHJWF8d6C7xC8czHnx1ANvEdgD8RvEAChPGcwex+oF7EDEvcQfF3KkLAPHOaiWPpi4iLwBADfxVsb-FUxU8VEBQJPAD-EtxDcZAnQJNQLAkcxQNFzFNuRoOhi0Bi9FgAIAYMT4bWQY8Hfo9At-ulzZ2FQcD6audjngmeAngV2QoABYMwAkJYRiRGV8DkaoFt2jCcwkuAbCV0yH0-MUDF4AzACDFeAHDowmEJ2ABwm1KXvpkD5iYymoIdUmwZowgOIuHjBvQcaKPBs+vXjInoARCcIn8asiQgCSJvjJU6MJAAHJGUZiVO460obtNDDMqiTtZnRFAGszoSGlOTJ3iCOgYkL4ngLYl4AZiYfRK8RCRYnSJASUEkhJsXKwksAESWdKxJzTLjTyJZ1jlwU0D4ru5TRLVpsFmxAqP9x5SwRo4LHClXkkkIAyYCkmn4oSUYnYACSbgplJFSWfjCJZSRImkgnXNGK5AcmD9GpgA9CgCpJSOltKXWcwI8Flyrlrr5O+s0dUldJ5QPbbgRs4Z0mKAP0XFFUKQEP1AYCzliMzQqSWGlFT+rmgsmsASydhaVGeySgDTJrgOHa6eentHZFhjBjz7tuHmMxHLed7kEAz6Xnmzqgmb7k34YmTPrcZ-WgYetbd+Z3n37oRNmvslxi5QBNGnh7oCNbuJqkfdpDaYKT9Erh-4aCmnJiyRCmGRZ0iclnJ6oDtGfeKjk-hy+rYj0AjmOyWpEIpaKQckYpt0dl4BMiKeUA+RH2sDCvRxQJ0nH0doZ2S7mvgvYztx3RL0T9EEIbKHQhwLAqFMa0mgiEshhapXyKaqIZKkZIGIYxrMaOIXqGgQ+IYaGCygtPyk4QtIUKESamIWKnEajHKRpSpyIZyFypcyOBqaauoQKGqpuqUZq-smqcLQ4QMoXakMhBGvqlfqMmuakrcaoZRoah3qepoep26sqk2pOiGqnChJfI6mV02YMs5Cpcau6mKp4qUaloh8muyF+psqcqG-qqaTyEGpfIaFH7q+mq6knqDqRXT9EUrnGl6piaYalCsxqUiGmp-qZmndM9aAqk6hIaQsH6heGkZquaJaVqkGxYflpzdpfKU6nuhQnp0EleuSNNAlwdwRJ6B8PCfQkgpRnEOnRp1oUckh2g6VGn9ECWibIkxTAgsjT6guFa5eYNEba6qo6qAxFQSc3je5V+DYd3rqyCvjX7qyHUXnaGy5Mi0hnhY+igIAeFnr2HiRhAuumlpOEJCkWRuDJLD-csHo5GXRNmj2nDpJIEtFGGgUVBlLpm6Zimrhs4dBnLp5kUF61AmXIAYYCWSq179Rc6cn6QZi6RumAZWXh4YAC6Gf0SMp34cynoeBYIKmup8oQmlwhSoaprNIvqSiHAajafKmWpvIdantptqQaERpBYDqkiZlaWxlepvGQqIc0MqTxmqaPqdqFWpbaQWksA4aU8wnqBYC6kSZUbKKmepEqTJlKZ8mcpqKZgaVWl5puIcJmdphIZiyxpzGeOqsZTIdJmKZ0qeqEZprmS2kqZ-IUJlhpRacUAFg5aQ5kwhTmYqEuZtGg-JcZZqUZmV8OaUqk+ZamcwAaZXaRBEJcsZgOmpZyyVso2QbVgsjEw2fHISwIKMRMlRBmWaum+BkkS+Hw26fMIrrc4hjOjGyNkKkDPOP5hz60RZKqPLMRNXGW6NR4Tig48mmdvZ5D6ednjCj6zRFlzZSYzBG6iRQKf2EZRpIVVms2qxoKryRlLol4F24Gbwl-pqWcikIZC2RtE7ZeKZNGaeHnixS+8a1mSnwpAEYtkWWb4SCy0Zz0fRlYpy1Exm6ZbqZJq5p7GbRqaeUWQ2mqaP2cpkCZqmXprqZ-mY+zLU4mTZksZH2QZnJp5qQDkmZaIQDlxZwaQlkg5SWWDmOay1DplQ5jmTDlJpNaWiErc9aR5kRZoooDm5pgmYlnJZtmStE2aJgP-HhRerK5oM5WWSYrZiB1CEYFJwQBkDTRL+qVmzhrOeVnJWLOctSQq3ZmIruODdO9I9AzztNDF+7WQgJuJ56VcgfSjyQL79ZRdIL5s6PUp8lS+94qyokeLFFCDgJgKRQ7DRC6QzlAZWGfihs84ydNqTJVuXBld2uUYLli5KGSimH0TuQbqr+Cke265I9+D0B7B-xr7p+2Njo7nu5NKZRlWay1A9nxQL0eh7RqzALGQBMJLJgCpCoABWl6ZoWZ9nhZZGm5nppCmSqGxZQadiFo5HafSEnqaea9m45IWfjnVpwLLWlqaJOUXlZp5ma2nl51mZXnFAaeZDn0h0OaXnwhcOTJnNpv2aTm-qo+RTnxZ+aejk05VeQgaTAWee9mD5X2b+oI57ma3ndMyOYPlU5s+Zjlp59mW9kD5FmavndM-eC3mmZtGufn8ZlOcDkV5BISQFDaaebMkRRrmmnls5TqkbLEOGApdpYG1epdlZ6b+ZgA5RC6WnmuOnqhkp5wToNcj5iwiM86UJbWba6pp56bAiD4VFtenPJgDiL4PpjivDJ65rYb9BcMX9LJI5wzKq1Hfpg0cB5zZdOa3HYAzuf0kIKSWGBmwpkyWAXO5OkU-l0F1TkZGzhbBT7nxea2ZUzcMacvpijeUOqGEIK7gZwXuRnuWACYAzeK3gMQoEeH7M5Q2nIUKFbeCFyjpwGT3zcoMeEbmpcujD1nuJUhbOHqFLeJoUmcwubIXyFFhV2AJakzE6DieDxgZboSRfhzTVROXAVaIOFYa9CAS83k8na5kEhgI3p3BhrgPJzYZL552W5CKbMEvuvMjQ6auad7m5MbgunmFihaSDW5a-j9yk+tCTvpoR82ekWWFu2a7k2aRRfYUe5e2eUWZFR2Z0G7CI5v94jQutlW5h5qMQLllFthRkXOAFGfnLYpIOApjqg2eGpjKFGWfMmUp5uIMUqY+6B-moKqQGtY8oUGL6a9GoVgAVLaFKXJiZ4QxVBHWFe2WCmbFUxehjY6VepkDNIjnCDZMiVKkXz1o1rvp7fiSdHVEBSjrliqBF-WXpaZ2JDk+lCmLFCq7tOLFHDpOFj7nWE-p53gul7FAxbgAHFngFkV+52TCXCbZ86fNlglimFsUlFoJeMX7FT2AdljFGxeCUoltRToVuY9+Kk5yEEBuiadZRGRdFolOJciWQlMhXtlIYqPHLgLi6WS5pDaDJVGJMlMxfuIKwpcLjA0Io8GzzfCDJKsVhabJdji44AeFYUKexyWKXdoEpXeAOFmEk5Z5MjyLyZTe6KkwrVRDLsEp3JsJWfDq5GBUEWpCxQpnb-mnxQNJHCPid9hB5htoxap2wJcCnzZ7JfKU1Fcqld4rZBXvZF5F04e0U9q4pUyWolTpf6WSlWJTZrOlAZfiU25f6qz43GYCTsGK6JhZMnhlIZT0XL2rmpaDslL+aoVmFCAOyVcl9DoGCTMi7kdH2m4Ut6XQxuyWoW5l2OCAWFF1ZTliZhADlTjIC9ployqlDwZcXoqmlFqV4wtyUyYj2T+Et4a5zUerJ5woRRBIaAxqvyaOeuQtFj8Rc-P3jEoWYl+lAllBX2EW5dZeyXQlghamay5LBb6UZl2OIGU0Fh5Q2XcFWKVWVblkZdkUb2S5QCHfutvqaISFeZmwGXlR5amXO6ukYHAy4kcEGgOaLJd+xflvjEeVgAf5fmWe+JcFiaAmeQmtZa5FJTDFAVP5aBWxwtZTQWQRSFX+WQqMucIi86fGEUK-CunjmKIF-Imsk6l-ZambDBBpaxHjlpKjfxZIQRRoDnYEvjOUoS9Erfq4iJKaVRd+A0WJEgl82ehUgVmFfQW0OO5dkzAQMKQ-6TJAlTljIVwaMeWIVglatqVFpRR6HflilXJXXlMJRRblRa3PjrieE6fbmSFUlTPgYVSlVHm9FQ2hgCsJuLLwAVqCgEIAdEDzK4AdyI7PNlWVrABqy2VgDA5VOVR9NoVRlVNuA5-uT+PxG1RiZb6XuVNlVpr2VjlQhSoVrmpFWeV0VaSCxV5yY2XbuZko8YF+nujVLcVeXDgTEVRfFXIPFQQLzK9ZLrv1nbKIkTgU38P2MxW7eXPhda+6LkN2Y4iK5bfIOl1BQlUGgHlVABeVMVb5Xbljpr9BDSz5WuYRVPVVFV2VKVYNXsFF5bOGJVfVclU+VCFKGULx1lUlXTVK1WlX8FDTlpUAwp2IOU-0IVTHhuJ8FZWULVk1ZtXeVqVbinmVaZUNqRFWZQumRF4Fb9YzasCCSWfuI0KA6GVL5QUU0Fr1TsUqVkRVhWjQ1xUpFBKCtkxF5cecHGBal2yiVWyZe-ugXUVmBeOjVV7EaOU0J+BUKYmYhHmeGTO0BeQj3pq5bxWOlgNfyZDVE-gUwSV5ZVoYA14WlTVzVqGTZqg1ylS9XM1u1btGkJIyk5ARAPQCq6FZdVedXkps4ezX3Vn5WoWdFlhQnnzVqKdSWTFT2HLWs1fpXKWclT2arWnlyGCrWe50lchi-lKFZrXtx1AF1yQ0ATDQSJMy9Kyi7a+URAAC0hPOqDJBVwK5WOadtQ7V8gCAMHAEAztYwT4BTwN0Ic0rwBkFu1kDB7Xqgb5JBrf+xJlMBXBgFXbWSBQIPwHx1kDMjCR15atHUJcOAS5p21AAEJVsyptnWu13-pAz51i8Z4FzxBoKYRJ1VwcXV51BdenUdEmdb7UDp9dYvEpMLQS3VAJAWafh3cmzL4IXMKIHHXzsdoOqDUxjgJWxd1rtaPV3clbOVbMAMsS0F5BsdVcCpykFTcBPAELvRrB1TwFsHDxgTL3X48ksaSFGAzmkPWr1JEZC4RWujBvX4gl9VmJ7OYzDCC71BIAfWKY9oZgB8AS9V3VRCLwSIFPAJ6k9HxQZLAgBXAoACfi5lNDOA1PMNBfuELhh4c+HlgonPHE1ghlFaHtoZlG4AWU5YLkB3gQGkgBPMYVbyAmA9cgBWMcpYLIAtBFzJOyn0eQENTUNfbBuC0AMDZtFrR1atIDINSYDjTsNIALg2kg+DYQ1xgxDQyAI6ZDUKwUNEAFQ0ycqsf0D0NMnEw0sNQ2tRlV0HDfaBJg5dL2kDE0gHw1CAAjRGBIcEACQ2yZmQas7AsEjVI1UcmrLQ38kYCq5XQN7IJVlINajeyAXUV1N3R3UfdNHSD02jecm6NJgAQ1jgBjUY1xgYjWY0oAlDfuzSNsMbI22NjDWVDMNDjY9Vxaw1Jw3sgRACto7YPjXg3+NTzBmTCNpDefZhNETQw1WNMTSU0ys9jTWBAV+kU40oNIAHTQKUODb416N4sEE2xgmgKE2Qs5jZE2WNkLNY1yNvTQo2JN4tck2ZNLrM401g6TSNpNN2TXAABNALm01ga-aUAnSA3TeU0yNdDWAptslTTQUPRjVKk01g3DXupZN-DTk0nwizX+omNYEUU2SNPTSs3RNmzYRw7N1TV5GKUBzfU1m0jTSc1+Nczbk2aA+TZc3LNM7Gs1RN-TVs3EszzWuEHhsYemG1NSYGg1RhGDRwDmUyLN80tNDyQC1FqQLeQ3hNtzes0PNNjU828NijRhEmR5tKo11NDTd5RotZzXcCggALammdNqzbi0WN9zWC1EtCTVU2jRC0RvDvNRzY1Q6NLTcEYXNjLYU1dNLLXc00NZTYhyQtpLS5Hkt4zZS2fN1Lbw3NNtLaTC3IDLRzRMtIACC29NGzYS0ytxLcM1zR10by0TNIAPy0bwgreq09iALZPk6terWy3StgnLK02ankQq3vNVLXlQ2tvzenYXNAOY60St+Ley1GtnLTQUM5cLeyAZ0q1KrQzNpzX60fuFzUplBtxTaC0utD7G60LZUbTWCuN4dD3Q4AUdI9TeNqrbM3zN+pVq0dNYrcy1pt+rQS0DNmbca1ctaGUhkqNireo2ttHeDS2JtcJSAAAtgbdW26twbem2PNYbSS2mtPLTm2WtrtDw2+t8zUxH9t2rYO1OtUraO2utTbbA3zh0YQg2wtFLfC1btSLSi1swc7YQ0LIybZXypteLSO2Gt67eG0vNnrRa3etilCe2VhWQAC0KwVbQY7iNw7XW2htt7eO2H0ezea11NVrfG0-N8zdxYXNH7Vc0qFNbVe2-tGbds0btouVo3tt0bctSZ0a1NnTdt5bWxCLtn7aY3ittbc61rtjbXe2pZU7Xm3uNvdHQD90MdDh1PMcwFB1LtX7Tc2stq7Te1kdAHco1dtaHTWAaNMGWB0tNmlJi3k5l7ex3Uc9beC3xmWba9pTtUzftpCdtLZ1SVtMHVGwrtknX+1cdJrVMnopzlXu3sgGeLx0vtGfKsCidBHdc1Ed8HSR2cdSHeR1ytUEa82UdyrT61qtibQkIAtBTBZ2wdQ7cR0cdDbXZ0Adz+QZ01ggNMDSYAoNJmAQ0aAM+1ud8zXeh9thje01qduHBp2lNpHYF06dQHVO2gdDHUiEXNXnSl3AtP7TZ0BdELch3ORjnQ+1KtWWLlSxdZbYx1vtSXRmred6nSV3+d0nRH5ZtcDdu0wt2DSF0gACLSZSYN-XaW0Jt5bZOj9tF7cu3tdmnYh3ld9nQrV6diFO81GdqHSZ1MVqndi3ftfnXN0ZdC3QB3ZdA3bl1jd4HU8z34FzQ1HbdbHZK17dtnQd06dwXXx0gAYXa4Ag0R+FF15AMXUp2JtTuCK0sdhHXB0Sd6Xfd0ydFXQ501NA3U+0-d5beqiYtWLeJ23dIPWV1g9i3YB1sNxzc90ndJnXuWid4jNd1WdwPX03zdqPQB0etXzc93Q9eXelCD48Pfj2I9IbST1dd4PRO35px3TO2Y9JnVmIXNtXCE0zdu3cj2ddFTSz0f1Ghb3DvNteA3gulC5HYVttJnU86JdRjck5FdOLcR0zsWnZl3NtS3Szi4lkJVO0Z44JezhqY1PfxaYtDrfz3Wd6vUz3C9aPcmWRQx3djiN4geITjB4MPU8xdeZvcXwM9G7Br0PdWvfaH1lyGFO13YW6FsVu9GuLT3Nd07lWje9UbL72k9OnfrUBof5c51ZYSFdtgho8vXD1R9G-q12pdJXVb37dCff72LV-VTNUIU8nWNjWtcXU8yNmmLZLIq9O3Zb2Mc8fcz1o9T1QN0foTWA4iVIp3UK0VtOfWJ0W9rLYX2g9bfQB0d9z3V302YLWNT1wFivbvLm9rHYT13No-Sj1+s8DMnmncs3MlaE8woJcFXASNBzzfuZMnOhOwb4v7X4g5WGPCWmnXsIhtOz9ViBrM1kGl7thYGElhXopcD3UdoFarg3L12db-WYgHQP-VmBAWeDRARkAJGJd137DvWIxzAB0Dn1KhdmzYARnLdSuAzALnXBQP0fvHFsM7P0B8A48YvFGa6HCgObMOwBgNYDDKTsCfe3QRP7O+JA33VoD4iZgMFgSyTsAShLCQWAsp4DEQmoD5AywO5l5pHkAED-kQ3EEltA+Hnk+DA3wPlAFA6wMMpmYLkFTu+paLUtK0g2QOyDAg0smKD72twNaAvAxoPoDWgwykfxBJXzkSq65tINDUt1GAA4AZA+CnOVACbgOMc+A7QCEDyaiepWD4ND2h2DNQA4NH01AwoF3W9NX4kA1XgzYO+Dt4GwMMpZSXoPhDPg-YM-RrgyYCPxq2eDGQxGXlIO8D1gwkN+D2g+hzvaDiRINtFlXvEORwkQ-4NKxBQywBxD2Q94PlDiQyYPYJmsXUXwBlg9kPeoKBBUPYDTg9OwuDwg24OV1yan1yeDHQwHBdDjQ64A+Rjg50HcJ9NZXylDYw4gQQA3Q1QMxD2PHEm1DKA4BETDeQ0IPQaKQ2INRlIwyKWkiVg50MrDkw0fQ6DVIJ0H0aqg1nrnD4w5cN7DUwzcML16Hk8PLDqw1MOmDUZenKkJ7QygNuhngD8PKmBccCzJDQw90zE5yA3dwgjYI9MNpDPhvRUnO9FYsPAjuQKCNXDSIxwOCJd3J8O8DCI1cNQjqQzH4ZDZHmENEjWI4iPvDn3lWgPD9ktIPEjrw9cPVDHw2dLMjNIziN-DN5SkCaG-hRBlwjPkY7FCAYIzgN9DQrFCNiJHWTZDCj7sVbGIjgQ6eEUjKka3pCjPAygMKjNQEqPrDnAwSOcjvA9qNijJIwMOHDRAwoHn5xQyVkYjd3MaO0j7I595zDUMac7EZ8ow7EexDo7kFbDdox6OKjPI80O+xsw5oZQGGo-oMoDNcdiOsjEo8KmQs0oxaOjDEY03FRjUQ2sMzDBJUpknOSmbaMiJyY7qNTDsQ4SNJj2cWCOkjRw3yN-qqoyUNUjxYxfRejhQ5NGNmjIzFLSDkY-WM1DRY3dxtjAY4jFBjBJa0UsKeWmGPqD5QGZwx1EI3GNmj0I0ED18iY33WjjObL6PpjUZZPknOk+TmMsJa1IuO4jhY4aOkDC4wPVljFo3UWzjpw4QIjjrgGON3cdI0EPF8zY2cMGDB41wPvDPo8FyXj247yP7VbmJoa3Jw49kOqYcAB0zjjfcXgNTjMowC718wo-AMmAgE9uPKj-Y1WODj6o1tkQ8VgwBNATS40fS7juCmhMwTGE0ePMxGYxDFnjqE-+N4T24zeN1FC6vePnjZE4vgYTVQ96OdjpIehMfjgYzzVhGY1dqpAjd3FeMxjhbPGPJqzaXKOajvE3BMzJCgYV3uJUkzmNXjO4xsNcDzE1eMETyI78anj4VbJMUTjo0EOoj9NfQO8Dcky+NKTbE72McTKyZoZnpNYwSOt4ubB0GCx9zYJPdMc4z2o2Tj0RJMqjiE5x7ITCJeGPWTrCW5MFjCkwaM4TvA9ED+TBoCpNTuEMdaNhhWQygNhTtkygCMTDY50GppNE6RPxTrkwaDJTHY3uN+TiU63HsTNA55MK63k26OPscFHaBvD5FEoWIDgzRVO5sVU9cM1TIXMrF6DaAC1Mmc5oZVMdgUw-hB+A6Y0XVxNjmj1NxV-U3FVtTDGd2RxV3U41O9TAQxDBT1w0-mBzTcVUA2ZgqQ3oPrT1ALBSrTUw7NPwUfUzwDOAb8Qf0zAxdaNNHTaACdM1AUEZNNnSBYNdNGUt03oMrTh00fRGgceRtMQhQ0-coNT7017m0AX09QCH0+nPdObatAMjC7TAM-GKgzMWpdMfTQM9tOH0p9r9PM5CM4DPAzKM5tPmhkMxDDQzTU1SEoz8M3tOIzWM3o5ozVmhjOfTyM7ILgzMWnjPPwBM-NNEziBlTOkzmM8jPLOlM-9OEzNM75EIi9M7tqMzvMMzMzTP4IfQJG7MwDP8zH2lK48zI0xzOyz34bOJCz+QSLM0QYs-tMSzMJtLN8zSM75EjuK9edPLT1MwbMfa3kmrNWaGs-FBazR9LDMjuesyzPKzz0bx7Gz9U4rMyz5s9+GMyVs4+w2zmYHbNEzvHgFlGUqAwPXygKAF0T9FWdfwHT1Yc8w2IAfjLHO11w0zPWAdzDGpYpzVwN+xDU8gIFxtMHTAuIKzBLI52TC--cnXwmeOMGp1AcjDkDC8oABiDxM8bNQAoQ9DJ4ytz3kDEDik3idoxjO+mDlzEOfnAOagkroAMF7BYQG4lgA3cx4mlRoViTL94AuOQgLF-dpfSlRlprlrduNyJvMnMXZMergu+Nfjr0UNCPqqD46YGtRuAh03T63Wr6Xs6eqejD8qwxDzKeyWA7rG-MYsELHPSNzsQM3MMMnc4HotzKEDPNbB4hlxWUJVMpiRxgl9IGHHRelkOYZACsO1bTzhQAfMjQxMqZKlw7frciBwKC-XzoCQShOgYUiNJOjMAe85pkHzhGPmLHzKAo8imgfg9QCXzVU9fN-Gt-r9D3z7HoHwcAz8zQzvz9LLwsFgX82CAxAv8x3NtzgC13MpAANv9YZcYjETri+l9HD4Sev0MR6iOEzv3bALojBq39B5CWeGlUWQDguzzwjtaZFaeuABISkbEKQsQB5C3QqHzVC+kAnzXqnQu3gDC1fMzAN86wvNpAqOma3IXC6yA8LH8wEt8LLzIItNz4iwAt-zQC-6736FksbK+IAPoPiX0MRaMyqopug-KggyC9cGSmBTCNUv9M6Hxhu44AJfRrMpUS5yZII0grbgO6qJYv7zNi5Qt46GlDQtnz9C4wu9TzCyqViMbC3nCKi2EqrHcLr84EvHM-CwgAhLP82EvuMESxIt3AmjPYv346ZrjCjQ8-UUtI0m1meG2GE6f1EZLpUXs6LFsSkZI1STxgYuaLCyKCj6BfvM0Sk01S9YvWwdS9QunzTixfOuLLye0t3zXS4GF7lviy-PUgQy5IBDLIy8ItjLWgACszz7NC37jMZCWA6L8w8x4kuQGnqPNQ6caH8XqLlAMUvCOVMsbIjSuSAUJOgWuYctQyLAsom85pkpkAaUu81Yu4L1y-UT1LDi7QufgzS48tROzy50u8yjyHGAfL-i0Escrgy8EsbgoSxMvhLoi5Mu-BAbsMnka6QLnAFCUK0gIPiuibzIsemJkiuZLMi+kkZcuTLkyrzuC1XqzL6QD7bxyLSKSs1LFK0fP2LjS-csuLTC24ssLHS54seOnVGyv9LnKzcy-LPK6Mt8r4ywKtxgM8w5z6IMhisG4ZExAotv0vRtPZpeGgr3oKrJS9fqlUrKopJF2k6LivGBpBd0J8yApWg6XL5K-oWUrty44u0rziy0tNxFq4yvWrLAkqJPzfi-atcrDqz8vcrZULysCr-UET41WlCWMz7KwSuIvNa9hg+WvK1ercgzz3ydMRkJnqrxh4G2nDONZ8L4gD6SG+fOGsae09uflF22UrAhsQBiyivbKksJxY8op2C1YZkaa9cGGrdiw0t3LOaw8vmrl6JPZV6XSzlylU0xr0tlrXyxizNsTqzWsurAq-eLs0MeISl6LOcK2sTLr6ywTsi4poGarAwKwbTv0wgWlqZccxVkAKLIzrzJe8YihgKPzGSyis-07ft6sk1XFfxbLrojNFiyEeOifMK2xsvqvkLe61SsmrR62autLMwDCtSeLHnCrdhdq3euVrD69Wvfz-yz+vuOf6x+tJYX626uMMCAhxt2RKjtxsYC0gMCulU+QvYaoWTimoJQrDxuMobrZco4IzocaxosPi0xMwKxozacDZ7lWGyKZXo7WlzLKuBVYExkLKCyRtZrNK+fMUb+a2IapcxrrRssEfMjeufLFgN8vMb1zH8siLfG7+uCbAGzxuAr7G8NK+bn6yJuJcJ8Hbl6FajqNkdlkq-SpyEXqgTqkoTEZstbS766uImShoi6qD48a6qgA+OcKXCxoHtrcg7r6JhmtGrB69mtWbea4a7Ub9m58os+OcD4t9LjGxWvHM7mwIvOrbGy+sCb760JuAbvG53M+bvW35uhbYm2OuSmznEloJLJ8GOtnYecLnxQ6apkhuiMim37wTKI0iXDpLa83psmYf9AD71oo2RYumbu62Vv7r1K00u5r9K7VtB59W-jrvSzm+yutbNzO1vDLnW15uDbPW-+shb3691tBbw299uibOMH9wx4eFewJjM8kpKv39hZauKnYuVWe3gAM82SXvrEQPXxj63Zkuvbbpi77pO4Z-az5VLx26Vu2LpG4etVbV2+IZ1beWZCCToDG65sDLz29Ryfzb222ufbXG-1sBbv22+tfbwm0BszbPyVchQYckhIqrA0C0BBb2IQJdY6q2W4jupb8cvFunYixV8pxg8a5LBU2UGHh4-02goPglbqW0TsWbF28euUbtmzRu3bhlqCA07bmwzssbQi+9tkqLO31v+b7c95t27I2zzt0a0-GMzalY8A5R+6CizCsMuJkmwuiF6S9LsToI8pN46MyAgUu6bxMpes4gMkkIjcQRG2ZunbxO5Vt0rJ69Qp2bN25Tvug5subt07kgC9uebzO39tc7bO47sfbpe6zv+bvaz-nqCk+t4snRkO3oqwIpMIvybiieNOvdCDxLdZG2caCLjqo8a1DrPik6UToTpoINrvmbxqyTvp7hu5nvG7e6XgurA+e0xuW7Hm0zuBbnO9XuhbFe7btV79u6Nu871NoqLDKknrcgi7SkfmKxoVO-JITEKW-WvQq5kh9V2e+i5jsFGxTNPYBmNkHYQmbZKydu670+2nuXbGe9dsMWlOwstdeK+09uF7a+x1tPrXW07v77LuwNt77W+wfuu7+fFDL5iyaDky4ik6L7tYipklaaAGhCwqvIbSAjAVQYI5kf0by6q4Yve6xgd7zFr9xb-v7zU+xVuWbs+zZvz7FOx+3Oq+PVAeOr967Aevb8Bzbv8bSBwDvs7iB2gfIHYWwqLWQXtl8J72CGySmQ7-wXMt5Zp2AnpLrqm3xbpcCyFfD6q+iIPuY7LgirvF2+mDlnz9k+ynt67pq9Vt0+oBw5sJFQroIdVr9LEXsb7HO5xvoHKBxIeyHUh72tjwXDHNsFb2By1ZQb6dudlgJeiXxbbyCO7gs0IYnliYjQmJN+50HK64ljE22RjcaXrTxrYcAHHB-rvWbNW+TvZ7H7bnuQHzW7Tur7eLIztiHJe4Efc7-h0Ntl7Ne9Eczr2XDrRryBUiOsKim9lmL5GLHsYGhby27EWjQoBESU9uFrpkeiMrntFhGyY89kY9ihRzcuAHnB8Adz7zh58qpaBS+4fusXh40eb7vh3Ie77AR6cdBHvOy-1mumIqfL9HwQJozpc4Cefl7pwpYkcnb3FhHu8lmSHv66bMKpKYbrpcFabdHSe--vrHxRw4dk7We2AdGy44Gbs1HFu-UdW7tazIeXHLR9IeV7zR2zvAbmjGNC6Mbe8puAuDx5+Y5cojgsh648e1LvIrZJYUz7udCmPY-ucx+-S4wOjH8VyEeMFp5a7BOzrsQn521CcgH5R7Cc1SKwA9vlrQh54ciHxeycfBbGJ+cdtH2+67uJYHG48bvSgBj2LQbMOgyTMEhh51qXW0610tzFxKDJKDGeuAr3R76C09JZmfc9yd-7hO3ydkbpO4KcwnLh7JKD4Bx8IfIn6+8ccCrrXgcFWRiCzOiy+-h36chhZp6BjBn8h+4L-cLoAu7rBiNOqgKLzBJsmjZ9FPEeaU4x5eE9uaXoT6wIca0UtklYDgcJq7bqj2ZrHmaxsclHjhzMC86XhXDqryFuuDtinLWxKfQHDR6xviHoZyEbhnQZ-P3nHXZwGfT6eqqCDAryZ8pv6Id+HhkhAkqwRm6qvZVXq72ZB4WcVy7fqFKpAgfPGuOCgYS4pzojJ6sDln5W-yfkb1Z1b6bWH7UXYJbN4aWsub3y4+sdn4iwOcFMgZ8OchnnMmGfPnkZ72vQQ5Mvu5j6kBhgLC7Lyft5JYyRz-RCbBp-zVDJPKCnLoi2CwWdbSE6F2LQS9+OuL72rB8Rt2HlZwKdz7tZ7ITzbOIr4nNntR22d070p76dvn3Zx+d9nD5xReDnEZ-P3ArIVcXiLz4br7rTbPiGzzQ6ZXN-TznKmzScsnaXtXpeddwU3uFLuC-rYhFQeYe4RAR23ae8nFZ5CfHn9K7hfnnq8hOlHpHp5Wvtn1uzRfv0750OeRn-Z7RdPnBlwxfXHLPMq7BGGAmxDQLntoqITeQbjIZdeKW8q6gE2ZtmLKJ16LitJrL9oOWLHM6M1noXye0UdHnTpzhcZKdZ-hdLliNdeePbrZ-FceHcB-ecTLj5z2cvnmJ+EV6XlF6ZcjnA3G-R6WDFggvySJawou2+6ye9Bf7ozEufthCxVNF4eryk4rMnGrcTDuCRloPNMnQV+CcKXoV1weGuKl-Wc4iQUlkCaXJF96fJX5F1ld0XvZ4-y6X-pyZf0XuVz4g6+3uuA63GIDjOdMCjWQTpjw5CHoVd7t+v7yGySNB7amHuC8IrXmPOSMpOXWQAednbjp71d0+-V1FeLzRF7eekX3h3xupXVFzNcpXxl2lefnLyRomkRg86UIEOsm2ECiKBDtTYnX2C3odaegWnEVAQLRasD-HE+i1W1cRubs5gn9p91f3XWx9wdPXF5yytDyr1wXt3nOlxMsi4uOlp6IXPtsGbnHVN0Xbrnhh3TdsQwR7Cr3BvMqslgO5+xmrs8u25rhQVC2B8dbLypw6T0UCC2dinX-+3jq-CkFZMrw7t16nubHBu9wfie0eFfulUhXoyqk3dR-FdkXfG4zcFMzN+Qis3-h0bc03LNwcps3+KLNoSkyriNBKJ+Bw2Z6KPKBoLX6fFn8ch7ozFCiBhOpzudK78F31zt+xsoUJ7O+NdjfyXh53jeq3hrurdZiXwu-0MWut9AdHH414bd-cTN+Qmm31t+beZ3xt9ndXIud-Ieq5W0oaq9GoDvYaSrCyDcHMCDlIEYo3IewcI7XDLvoWVydB2SVQYi-Iguvi1l8Vs8n7Bz1f43cd6PoJ34poV4I6I1-TtenSVxTcCrFtybdF3HInnfU3i92bdRnTHqG4C4wELGhoOmp0z6E+4btmY-V1V9xb+G4zgLhmncF-xercpQuPQtIOxBN6R3g9zHelHdPvHchG49-VvuniJwXtp3c9xner3hd+vcM3+d5bc53y9yXf6IIzF52DBvtAivg3n7mtz2cCcmZJd7GJtgf8lZ-RDtiXhi-kZm6ojtlx5L+O3Jcv3M+8Pfv3o95-da3hwqdFT3MBzPeiH6d53ML3wD8XegPQD7TfF3vaxOESm70Lnx3iWuNAuoSmBqwLridCkrvS7vPZLIC7nwoGDHCm5y1fKJsvvkZ72z95heKXYV2rdUPmt+-0GWCJ7evEXCV--eonLD2A9r37D+IusPXD5A+9rqEhpSko1cnDpXn0C7w9zAcS1TJe+sN7gtzofxdcVXWO9wkLeXYjDuJrJvRiXBvQJCwPcaPQ97HeUPSEbo+FeCtinfGPUpx9dmPnD1beQPHD1nc2PwZr2shAy3Iaran0WzCqybToG14nR+fAGGYOItzLtmyBYvqpGH0t8hut+yAo8dXwe9rJdsHMT6-cnnrwTo+J32tyWv0PJj8+uAPuT1k-03Vj+Y9sPtjwDDLcYjOKaFMRJVAusQKXBZIv9qBSDvePmSyLji7fFjiA6KIBrg+iMhOs6qICOTIbZRPpD70-kPcTzMAf3iTzlzZiKT4lfT3+t+k+OKsz3k-tGMz5k8QP+TxGAqunFgWLvKBQs7cKiBGQkWRPcC8yR1PUa2AsySQ61on5nN9zosmLp1cMrqPIV30-0rTz0M8O+xwqM9pPPpxM8F3vzyveTPgLzbe+Go1R3uYLSOCZKyb5ekbawFAjxhSSP-F90IIbxro1sTnW3P8es8WiZuLsisSji8On9z2-ePPgz1-cHKP94Y9Innz2S8ZP1L0vfTPlNz89TPtL35pOW2h0bbTEb4r7thWRtutyXmkno3fcvd4t8q7nkzBN4o38F2yexLVR4Za6KcYErf2HSlxnsEvcrwKgKvN53-ekvzD988Av6r38+avob+vfBHEV16ohGj+-6t83BKMJfpbI0Posh73MkBACvoji5AkR19--vy7jAmPOZbtpz0+4vUr-08+vND2VxNbir4G+MPBt6q8Uv2r1S9NvNL4Dt3AGSjnCgOXj+PQkr-R21bLcPQCQ5TZf1gmX37er3fgbym2yvOnPycmQlgYXYkIiW6Er7jflv+L7K9VvY9m8+HHQbwA+Nv4D2G8tvB71G-reWp7teTO+j5C9TRWjDtfEoEzDzkJd4x9bCZSqbwGHJopNDlv5G5WN+4TngVSu-R3a7968bvkzvmLBmJL-W9fPFANY-NvGV1B9avbb1GffnmC6NCirXyoBfpQBdux7T6GQNxDOXqm4Uysn-3u5jCIpoh3egbIT3D4src-EXf-vd14B9z7lb+-0Eo6qOB-Kvwb1B8w6icrnDsnXXgzecfWJtI9hu7b98kHbKchAZlcj85fSnY-3PWjrBsb2XKD76b7YQuqbqncEA+r+8FcxYcvsSsYb+59E9lvQBw8+sQs2pmJgJFzwwrbvZNyifjPLD-x-EFPH+VxWPdn9x9beXXsCu86sOnmfqb6ZoD6JLo8BJ4ASiC1vIfv+H7zmRPB25Md5ZWJLg9ZHApXhU8o8toRg3Ppb5K+Gf0r8Z9M+a3C5whSaXpZ9aX1nwge2fXDFx+CfvH05-FfAn2wKw7k6Dw95MeGeOij4ozGIzV3RXu4-5LDdwPsGn2RpN7vSsj2f1kfpVI8GVUP5n8GFitH8rdVn9K8TKZf3Ftvem3y+7-f5fDqw2+OKzn6V+OflN2t9VfQn1Gf6YjloHngJBjNsn9vxKWAkkRxos4nVXpVG7d5nY+odXQyA35m+B5zKhtt4V43569aPhrtN+q5s3-wdoX9D+TemPq3xV-2frnxt-z3W3w5-Cfijt9hvpU6ZPprPdwO0uLlzAvy4NLXX-w-4bAJnxjwv8a59VgOJ0Y1uFZN1-p+pfKt+l-pQJn1l9zfOcKyuLfo109srfHHyD8uf1X+beQ-YP+28k0elx65sCYCRHf9vE4S5BZcyie5iKfN92kfOq0EjFj180t6IxDrQzLcZI4O3x69YXXr3Pvffpn9l+yEdP7W9LfjP5B9NF1eqD9s-sH0b8lf2325+6FFeumTNWmJJC+SILIkaKDcVRwacb+JiOPqsqqpQ6-cvDxlet5bPvNF+q-mjw9cDgVP7985f4vgD-vXKr8D-G-rPzt98fLP+t9c-TRcEYPydnj7Za5Ci4zcuCgJ8L-BmmZ6k7BAO-s6qs8nVP8fFPDS4CaqoJJe99q-n33T6a-1P86ojP9PwleA-Nn5ejryUIPqrzLsn+D98bTHk4X5iqFnD4hP7b2QnDSZcvD-fYsm6LsftujFolV64v3g9hSnPI1tWRieGi94PJH16r466mw496ftzwZ-k--T-zvky7mMSj8lcNQl3R-y35B-D-vf2P9Pfg-53NP-+Oi-8D-7b7xgVuthMTLEocXY2XSsKDyIpihSQnxrJak6ZLS8xcyHWjF4PjDNfWd7QXB9zGBOSRmnBHTB-WJ4U-C-5KJQug3-KW55fBn5MPPd7d-Y6Kf-XxCv-fw4f-Uf4UA7-7yHTbYfCU0RAGaLbz-IWpzAL4QhSL7xcvNf6YrStycnKECdZIV4SKW-QMKUD5EOev4h-Ch4ggc8y4A6-4pyEJ7DXdv7vPZQHaXIH6vBHv7kA-v4T-WD7UAvv7j-CBwzzaaAXmL3g39ezjorWTbNaDxxlcQebMCVf7omWb7X-TEiBmPRbMnB+77KS3RF3Reb93E-5k-Sb4Z7HAFX-H7zf7ejZKAt65jXEgHqAsgE0ArQEQOc466Ar-7aAgp4biOXYm6AYLTnfo4hHOPbvSTbgJFP3QuXNvxpcDfzXmb-Y+-aAEuCE4qZcPGCTGCQFYA8-4yAwIH4A9cSEAjv4FfcQ7xA2gHaAuIEaA6IH6Amr7ikGyAjMOHTjgQ6pirKFb0qHN5I0TCRlcXx5XfEmK4qEaCx+Q+YDfVAokletCDlBhTdPDC6n-PwEa-eoHg7IIF5wC7qxXcU4qAmP7sfdoExAt-6kAkf56AygH0AvOBfmEBzpmN6CGySVYDAkXDpcdc56WbjZXfchLE6VN4ucYIjZbTHbCAquSKSQrwHpTAF4vfwF7AvAHn5ONDVHPX5EA955M-C4G9AqgHdA24F0A2vZzuCWDrJRLDFCYAGbkP4zxyOSS-uMNz49Fy5rrd6RO4ey7WwJq56MINwLbWzjX6GoHQg3YFFeBoFzrF-rNA04HhAtQHdCB8SWXN256FYW7nHQUHerExamSLmTqoHh57uH8xXoeZAFCJiKJLKDCbJFARiMEhz8uA06nmB9xjMYRAG0WhQtPMkq7nTMS2EQb4zAzq443AD5pfc-6YuWpaUrTXDXoVj4ogyD4SgwoTjoaUEl-fw7ug4UFeg4W6erUDL87Xx44bRcpQrEuBMCGFTG3SPZuOX4GUnH4RVVDkQKPR14g3QMh5SCZxvfK0FR3Oj62gqb72gkjajMK84ug1QFd-GqJCgqUFpmMUHiLX0EVg0UGygslR7uLt658MICkFJ+onfHXwvAhKhOWIpjB7MzYPuIGzkgtgS9tIfYk0AXYCuVYIuArMFkPXMH+A-MGYXNXLFg1oHVghyySgz0GVgs9LLgvBweg3vTrgyf5KRWaD1rOfgueNnwKLQY5iKMuQxYNdZ8Xf-bLzNk5oLQ4FbbG+7F2CUiGyJkTHLMKpQg+j7cHPdIULCs4lwRQFIg1J4QfWP5lg1cE7gusE+glcHbgkUEygyf6e2Ew6fKKnBfeSF6DcUDZUJSEAuCEL5WvK9zgISk55SSJ6uA24y2ceXIvPMQFsgr8FffOcG67Mey6-AN563V0EgQmsFrgiCGwfJiHgQ2CHyHFiibJBEEtWWM6C6Xm4fuSAqGg-nSuFE+51PDVrIvSRQASAELAgm+5vg9MjqCR4KLlZL5bA3wHYXb8FUQ9Y4-7RcH8g0sFsQmCHeg1iFQQv0G7g+Q5IfHr4v2M2IiYcMGFPF9yivG-pNZA04nRPJYcVHMRe7VwFzbbLhpeBrKJybwEpfVd4zgjX6aQx0GFMBb6AQ5QFjPQr4aALcEmQliHig4yG1gjiHAbG0z3vHPjnnFUHikVr5TpO-CwIYoS7Pcg6AGfQoSKbA6oFMj7oLAVy+0FLRAUTYHBXNSHq-DSGCldg59HHSGz3AUEJQ5iEcQ+KExQxKGGQz1bNaefgOPKvSJrSVa5IQwrQ1MH4e2U+4PEb9zJoFLTYrPN4rbYwKnmTIAeqMhCA+T8GBQhqG-g-HSsnfY6hAz05sfCIH6Q-0EbgiZbHQ0yHArYf46nY24LFAAzhghziGg9T5BuV54fHZDYIWXy66MCyTdhaPbzIbtzfucVYjKEt6qQgKFn-PMGNQlPaSXWiFxXCKG7vNqHdQjqGGQrqHlghGEBgoHYrLAK4c8ARwJlRJa-eP3ipyYeS57a8GaLVZLUgwWpU7D95B3Nda-cK7QwyWM7kQzaGUQ8GG67AiHHAls4ww4CHsfc6FxQzcHIw9iG9Qhsx25NG6ZcWBA1WB35-Gd2wl2YoFs+TM5GiTbY72QsGGQn6EkRZxInLD4HC3DaGgw2cFMwupasnJ4wtQ4gFww3mEGQqsFnQ9qF8w1GHiwN+jdifJaw7SWTsXPezs8L9x5Gdx4GnHMKSeP148oXr55vFdYJ6IuyUnLUG7uemGawoKHawzNaS5XkGRQ8Q5cwzqE8wsCHGw+sGqCUapDrD+hxfS1yJLAGxYGZxIGWIJSWvXf4-vTFY6JXDI7-ZDaE6OXzHXExb1rIOE7AraEOg8rZ9vfWFM-aOGIw2OHQQk6E--JSI72OIqy+SY5RHKD5v0drQuCGGT1EPt75Ai3RU4dgHDJXa7LA3LQRAAeYOkf+gaw6uGMw7aH7rCOGwwvSFmw+OGQQ+GHmwhOFzAOzYTMfUGQECUiI-NsLfCEGz7PZohq5e-Yx4KuQ5KNrTs0YcGY7LirG3EFCd+I4STQqcF3PBmFN-YKFGrPDJrwjmFHQ2lz6MOm5T6V0BPGeKFPHdUgHKcBEdXQwGlbbmTIAonT-0KT5YiLchzFLW46MOwGgbAraF0X3xu3fzZ4-Id4rQsaTsAj8Gk-EGFLwpv5NFUFC-0FLSQVPaHhQsIGtQjeHQIziwySLt4dXKBEV6DhE1SAjxPGT1YduDqgm6WwxySASFTpePyxLSu6QrV6FnPdsT2LeoiQuF4EeQvYK5SMaDaHTdbH-fyE2g4OHfg2hHlRKdIOkfPgsffaH6-A2FsI3hFgIrhGQI5cHsI6xECIvoHUKJBTugFC4QkJyDHCRJYOcf8wmHJBFGSfKHy-XZzgggREs8DT5r-cXY-CO0yFCJoFfw7YHqQr74GI4Nz2cZ+yFCXkGd-KKE38exGwImxFXAzJFWI7JGOIrn4qJTniUyfZzhucMFs8CIB62cBBvSHB4yw2ZbT6SC7jzOX4IXVVzKbaCBnYaYidZReHxImhGe6QxHJI+4Lwve-4G-RiEgImBGcIwpFGQrJGTIiBFOIyqhKHKtxT6SfTRfRJa--fvYwApCHRYV2Fd3ezgHCQsQOUBkGiOHCqnaEiJV3WJF1Qxv4ggRJH0I+eFqmEZGHQtqEzI-hFzIyCHPIuBGCIoID2g7lB6VZ8TjMcG6OcfLZOFYuzrnNByZnMpG20biA-yKY5lQzBaNbPCrZLLxZ+Q4GG6I6hHXI-pFJIhhFdif17QwlhEWIjJHQyfJGzI7hF2IolEvI+BHikWhG57W6wd+H-Yi7LPjV6Jg7qCEcxQAn2H41PZbYHPRZgo5+FGHZI7huKtwa3KuG9I9FGGFTFHpkTrxpIs4HAI95E5It5Fkoj5FOIsZipbUxYSGEBymSKFbnmdmhmSdwRJaY5YQXIyzWXBZa+PFpHdCRdajwJ2DVImqFdXVFHConvgYo25GHKN26Soh-6MQzewhFfbay+IrQ-XOtZuo8eGZvAR4ayT1Y13Y3787Df6rImcajOKWjBGGLBlyAJHJyQrJS0PVSvifdxlQkw4N0dFa8lHZZCo+qGGuBKgjMDREkQ95QLgsxFEAxuG+olf7BEIFHeovjbBGfNEVoz1Fnhdt7BESeyPBfQpFJLrxJnCK5tWOWwPBScFPvX27CAntySKd9auAw0GfCLu5ElBs7aIlFE5gvRG5o7oD5osNztOA4KPIanYloloG6QglHloj1EBo6tGdzWtHuoyQwNowNGSLS-4keXvTf7TsThg+oEIrfQIQGQ0ROQr7wtVWM5kFI9KV-UebmokHZeJbNFXIomRzuAtHLooAw4ok4F4ostF1fP1GVor1E+g7dFHo3dFc-TeyOCCZi96fwxq5IpYLovezj2X+Tn5bIxXfelxOKCA7ZfUoGE7PkoAXUKFmnFSG1QqhG2ogY7-opdHXfEHamI5hFWfTdFRwmDH+oqtHQY8DH1ouDHyHNZgSAKGS9YXxJfeE8F6INpzuqNLxpaKAGlbUgrqbGVYkeIjF6XaYxI0bswaI4ZKnRHpE5o6+YLo68xS3ejGaUB5EMQzmFsYyDGNo1iHGY49GLXHe6ZKElL7PB3zvHaBa+mRgRhfSebHfftHExI1EYif8zRfHLZTbJG66MKWjERH9Gh-P9GLo3THZLBrI1vOiHIgksFborjE7ojjFmYuLGwYhLFCIyArrJQb786VCwO-TICMAydK5wJRKso+X49AfZzrJF4GYQ1wGxLOyFpyEaC58ILFSAkLE6YwtEjo1mFGPPkGjIozFJY9jFQYxLF1o+LHdYsbapcJrKgfWh7Yw5FYLo3xBBKc-J7OHJi4Y58SpyJwrrnYn6B3TT7Q1Vm5VAurFGfGjGhYprGiUKGEgY5jGsIrdF+GK-YPBBs7ZcaDHHYgnTaJHETnYku6i7PkpHCPM7FPXuFrA8ZTj2RGieLDc7pvYoSNZUNw4fTl7MnX1adeDRELvDLaR3FYLbXfvC8-IZLUYzA4-uDgGE+XYSRYmhgvbBh6PIvSGfmWJSVoHo4ftNArVgzHEnY67E02QfDS7U7TmSSc5UHa3xEghZF6LYoTLlWsh1PUSh-BQ178PKWheXTHaTpSeZ-Y8hJpHcHFj2JwpQ45eYw4zTFuLaB7w4nl64iZqE1HVHGRw-HGXY7HFnYzrLiggnFXYnHG3Yz1YiKShKLlblDDJEjxjAwUo4VG5C96XI7VXYX5f5VxHriFzhlQs1GRbbsRJaEn5yXCHEC4wb5XwO4Kw4sXHaJCXFZiYl7S4kQ5o4wzFHQlXEK4m7FK4uXE-nVXGK4knEa4YRy85AEKVoIn6SrT+SSmAlBQ4s8KIbaXYkpcHaP7WRY4Y2d6e3B4gb+d6RMHPnHaKWhTQ4t3Ei4mcYKST3HgItQRrowx4y49eFHY8PHB44nEXYlvGnYkPFR40hCYfCdIAhd9anReC4HCFxQbrX6Gm6bgGiMQ2yKbKfTKnGTazvEGxirRdbanXJTTolBZO4qnYu4m7GrAX9GyZavEjHLt6qoMKEubRvFAIgUFB4zvFt4szHy4i-G449t7eJWQgdUMhDaJNC6qg33hQ4tVAk1JebTrXsougQw5BKF+z6YZk7e8bQ7PiGrFxLEvGQ4zfHC4nfFw4mvEH4-DxEXE-Ho45vFY4m-G3Y5XHX4onG34+gGfyUEjduAUrxyJjr9HDtyj4LGEOPSZjSw1Ta-QTN5-JHD4r-Mj7lwjpFjzZtJd3VfHXBdfFl4oXEV4mAke4-fGI4mbEtYpAkB4s-GYEtXGh4s6Hn4rAnq4r5HT8YCCSYqg7sAgSGcXfvDXIdCS-4hKiFY5VFZcQSKwISUxEE3FZkw6GQHBFB787CAnO48vGhbHgl74hHGS4sD6+4xh7+4mLGsY0QmR49vGoEqQmdZOx4pcCJ6SIIpKwyCRFMeZ6FMAhhRCuFy48MVlRV6XKEviQHFpaSAieqG-r-5LMEcEwXGu4ywnBY3fFO-GwlfeRAl+42XESElwld4twmE4sQnd4tEwMqOPZEOdsQ9mBRa+mfQLsibA7aebgEorJ6QlCNjzZmYNwMgkjyg3VArYSGlba7ZIlQE7gnpE2Al8E3ETMqHIkOEvIk+ogomX4jAkd4jwnd45-qDJGbT5LOSTXGanFJya-46qaREpoxnFOgk6K+PPDwKYhIrM+AEI5EQrzGnMwkb4iwnb44Ym8ErIkBmYDHUgIQlOEsPHuEkolFEiPGFExD5PHYMBx7R45iQqT7-cLQT5bSZRRo68E+wjxyHOOfhOKQAnz41wQwyM8JzY1JxXEzgmpE24n1YjIni42vEjVCYlAQ5AnOE+YkfEq-FEk1wkl3OcodLcUwoWebYvYwp6riQAyOCcGoKPEPbXFMyQiw-VSgYbiq6bPMQgmFC6iQ9148nAYk3E93HWEr3Ex4ACHH43IlN4wknvEsklzE2UnfEvqE2mPM7Q1QAxQrCknXFbKRGiIM5pvfi5YmK9w1SSZQ7+BglYvcR5SGXJCaUfon8464lcEtImYkkYkPEwXR4k9mEEkt4nFEuUlukr4mX4z1YqJAxTznQYwBmWTZcQyTxzIyUx2cU3E5wnIiBhEhw641wF9RPbagYTCQlrK0ml4lIlb4kUmZEsUkeI50k7vU-EY4mYnYE+UnukxUlkqehS+6QPIEglC6I-ByhaMCRTxbAPKSeb-EaMFC5WHNQTQSYuFWwi67LQhfgF3VElpk6Al3E0Uk4kxAE07F4ncrZcB1zDQIL6C6hWxH2BdcdUAdASdjJ5EwAzAB1oLcFAD7AMGhtcOuZkkZgAHQDyoQAKEqntNiA7klgD7k3eiHkyOBfADsABOUoSEgaGChQY+ImzTVhvxS0JlWCqyysU+puLUEA3UUgB5qb+rpQJiqIxFwB1qDoAWAeppsAaxJuALkDxMNgA4AAwAVAbdDJgYODygZMDlgeUAGANgDJgMJiwUggDBwcsBsAKJjxMJAC51JAD7AGTA+wRsBsAH2BIAH2D7AJADWJIsAgAeBgPMfCChQDwDRAf0B1FcmS9tGtxQydcyx5OQrWhdDxMQQ3yC0RdIxzSYCssJBKxjW5gyUyOCRzTrjvkgmw6IAIIOARtgG0BFj3MTwBFgFFz8TEDiiceAD4tDAClgPACzkQBKaUxVCkZHojMgR2QSUnXoJcaSnqUj9jyUsACKUygT42SqyqUrwLOUp5iZAaeJ8pZkAqgdDC6UvUz6UqNguAbliIAKJomU1wDmU4tj+UjVI2U3cCOyQDT0AZMAnAZUxOU-KL4tbKlMsdynQLX9zWENSk5Uwho8oUdgmQaynvaZgCOyU+x5U3Kk+U0qkFUvRBshDiAlUxti96CqkMpHtK2UlFwQheqlRNAanNU0hAeqUCDtUi5idUpDgouNKkZUvkBSUxqmyUqFiuU4ameUsakLUi5iWU0tBiU+gB1U9anMcZamRKZSleUtql7U0qpdUqYaOyfqmnU-jh7Ulakfk7ymuUs6lWUxgBe5XdDzUx6n3NIamHUkamtUuyDjUwhpCuRQZHQXHDmwUELTUvOKZ5YLIssO5it4S0DyNKymyAVgA3URfAJzFACQcJAi3cXakfU7di3U76n7OYqnXU4mTnUo+iI08Ogo0o+i5AdGmUbK6nY0yTpfUpSmmdRswnUj6lE0hGmLxZGkNqQ+j7sU4AU0rKnXU29i40hmmrUh6m+UjQDE0-Hjs0mCZhzBTCkABPid1WubXUnGkHUhmn-WNaks0yWDi0zZhrULmkQBe5iLxMJhS08EYgTRjiRUoykbsWKlmUvuISATWl0YEGbZqUgCYDFoKk0jmlGUcKmfUwynRUqNgW0+KmpsVmlbU52mG0xiZtwBWm00+DiC0ygSiUNWmi0imD+0yWnk0rGnR0pWm+U4amR0kWmlUilCx0pGmG0mmmJ0umnh0nGEMUBxiE00SCZ0vAAG08mmL5KGnpsFdhw0j2Ygte0Jv+D-yKYb-xd1UU5CLAgKeeH4Kv1USm22UkJ9VVmC7gBOnp0z6n508UjaMKOnD0nEDi03umHMBfAx0EOnR0gWnK0jyn3U5mnR0-qDT0oLgccNAAD05eoDUutr00iOnj0tOmNsKelWU9ZzvU3Olh05ekF0gmkfU82RA01mAg0mYAnqHum6OS+nD0pOlNU76miUO+nR010Cb0oelbsPOk30semV8NenD0gBnn0u2wL0z+kgM5Ok-04+kQMxthQMram22SulH5E2kw01DjlNcWlGAboAwAD+nAM6+kIMhmm9YP+nD0tvZ4MghkZ5JalX09NigMtzArFE+kTUhZDUMvRz70kemMM2pET0jqlsMqyn4MoBkNU7hnMM5BmsM50DUMnOlwMkhnf0shmiMv6mE0-hlbU-Bm0Mzhlf0-KnfUnhksM09oSMgRmY+OhnSMhhmkMygRXWQun-UysK6M5Rk1eAxnEMoxmyMkxmmE7RmvtPBluzNRnwM+xlSfMcq8M1hn71USlGAKVxuMmRkaMshlLPbxmntXxmVUowDLOQJl2M4JmUCFQmx4cxl3ACJkMpIwAcMxWnuMuJmX0BJlhMysIpMqYZGAIRmDU0elK5BdRiM8JnUMohnCM4xnZMkw65M5Jl4MvXpiaOUJYMmum4M1HQF1BeLKAY0CTAVinsAa6nseIgkTjIYCXUbgDGgPQaVsReKH0XQAKYPIAAALwS4fTKSZgzP3OxtIvskzNYA0zKEAszNoACzImZnTNIWRgF6ZksWWZ8-FWZgCSB0BzM2YBpk6ZVlW4AIwDp8tIBOZAzLOZDbHaZUuluZVdUyKt3B0ixHG+iMQzAAJIGmZXoROmYcEEG6YyXyk7ArS+AFAokgFngYgWMI-zL6m9oBZA-wAwZNmShZuqRhZ1IHy48LKI4iLPBZR9FzYloBuoXXGsZkLMk60LO6YyyHuAeLLPsIM01ENeXpCmLIky2LIsAFsDpZJ3AlpZwD7yBIRZZeGjZZE4E5ZG001EOOWZZlLKxZ1LI+knLPriYcA6md3Euo+PFXA+QQ2mLgGIANPApZmrCpZsLJUc1QQ2mKnHyikDBQAGrNdS-LPE0bLIGwt+hggCLLh4f+0hpb2TNZr6jZZfWHactCBtZZIQg46LPFZWrMlZoFEvgOp1CAerJBmcgAYCnc3tZGLIlZrLOpZKVEqoY8GqC0YS-AAfQ+Y6GFJCuQDyCCLLJISLPtm5RAioRoEHozTNsZ9gF9Z2FCWwfwSDZmbMJZ4XBzZY8TBZXrL5ZkbIFZ1LKVEgbm5Q5bJI4DKRCii+FzZtbILZxlOLZFgCIw6RzLgVmmEpFlE-KfzMrZXC2DQgbFzGVtgXEmrMhY2rJLZGlDbZWbJEScEADYuQFzGhoBZwaADrZhbMhCUbNpwS2GsgUiAzZ7bKmGU7M3Z7oTggpAA4g+7L7ZR7Ndw9wGNc0pHPZa7JgAjgBJAQgAAA0hDTD2RGyfWU+z4sMJhmcfGzwuKWBogHOz02fiyK2UslBWi5M52Q+yYqf2zaouSdA2e+zK2Z+zrqKbVkOXW0l2fFgX2byYMObByL2dcMagNEB5aeGzvWYuz+2WjhF+MKyCWUskHQj+zgomGyAOTRyi2cBzoQBIph2aRy12XBB56nhz7mgRzLWVLdV2ZWzogFCU9AH2kF2VxzG2ZYAQID+Yz2Y+xrQqLxf-ExyGUuDQA2CayHWQ2zzWdSyR8I8ZFYJhylkjkB8IFFSEuHJyOOU6zqWV5hwHCZzVOd9osUhOzmOY3SCWF-4f-L2yUOcBzi4CgIJOUskOAOMEwpsJzHWUyw2WWjRjTgFyGUjsxwuOMEwojZyD2QRyE8OHtouVMNWKSFwdYglzrOclylsBVc0uUfQ7KdjFvOfhz+2dvgZWUfVHWLTFbRDv0A+p4wjmTXUrgGyFL+ssAzYo-1lgMUB92Iexj2DhBl6ngA4AICAQACSx7KmQEoALQBywGSFBufmAwABwBGAGKBywBszumFLpywP3UC9D+wJuWQtOyOyAywKylxivByakvOMTONTw4hnYwg2MwAxglgAraggBCXDhNTucyALufIUUAkXNmANGIyQrrSDoL+x+APIEABNpzA2Pdz-UJgABEnElGkigQGCjMpJwulNZGEFMQeRAB4mHdzdwNGJfufYwHuUDzkkmfhoxJAwbybQEcIM9zxwuL5IecUB+NM9zoxNtNieWdJ3hmTzbudez-uVgBaAmMBuAJgMnKk-TORi3MvclxSrNMQBowigEu6kGdhHLONZxtDIAsigE2eclZ+YmF0cEgaYLbJLFW1OJx+2IAkcadJwcZAgBZeW8zimYrz+PO5zP-NUAoACrz7JgryY2Fpx3ouTEvooSzdeXxx9eXOx1mdykzuWby1mdDT1ed+wk8rGRbeRczWmQby7eDWIzajF0XecWwLebuxnQrKyMwIgBgWUqzuAD7zU2H7zaOAHyFsr2Ak2WAAU2bmxWEuHyD2QJwXNKOz9+snyGqQ7z52KyAIORuhpeYNRM+Wrz3eYBU1OZdwi+QfSWOIhxHNKOyfwBXyR6dnzo+Q8xHWPXzI+axxkZtLwORrgp+NPOIu+SGoFps-B++V7l1yQ9Qw2aU5P6tGJhAIlN2QG-RjJCAAbAEAA

(That is an actual save after a whole lot of playing. The last one I made before I decided to cheat.)

I have dug a little bit into the game’s source code. Turns out that the string is a “encoded URI component”-formatted LZM-compressed JSON blob. The compression is done by a package that is available as a NodeJS module. So:

#!/usr/bin/env node
'use strict';
const lzm = require('lz-string');
const fs=require('fs');
console.info(lzm.decompressFromEncodedURIComponent(
  fs.readFileSync('data', 'utf8')
));

Then, when you format the output JSON with jshon, it gets pretty straightforward. I went and changed area_loopTrapexperience.loopTrapMultiplier to 10000000000000000000000 (I’m not going to even bother counting the zeroes), and did the same to area_constructPowerPlantexperience.loopTrapMultiplier. You could use jq to do that. I just used Vim.

Just for comparison. My loop trap multiplier in the “study mirrored ship” skill was just 493.1. If it took me, say, 100 playthroughs to get to that point, getting to a value of 1000000000000000000000 would take 2e21 playthroughs, give or take a couple orders of magnitude. If a playthrough lasts me, say, 1 minute (I’m being really optimistic here), and one year has (being optimistic) 600000 minutes, if I’m counting correctly, it would take 3e15 years of continuous play to get to that value. According to Wikipedia, by that point Sun’s temperature will be below 5 degrees above absolute zero, and all planets will be detached from their orbits due to stars doing gravitational stuff to each others’ planetary systems. In addition to all the silly events before the 1-quintillion point.

Okay. Then you do the reverse thing and make a save-game string from the changed JSON:

#!/usr/bin/env node
'use strict';
const lzm = require('lz-string');
const fs=require('fs');
console.info(lzm.compressToEncodedURIComponent(
  fs.readFileSync('x.json', 'utf8')
));

And… When you do that, and maximize laser gun, your laser gun will have an effectiveness of only about 7-8. I got to like 2.6 without cheating. So. After having been playing the game to the point where Sun’s light is a distant memory of what Humanity has become since its embryonic existence on Old Earth, you are now about 3-4x stronger against aliens.

And it’s still not enough to beat the damn game.

It’s not enough zeroes. The aliens just keep coming stronger.

So I went and just read the source code.

Turns out that after you beat an ungodly number of waves, you just get a message in the same field that aliens say stuff like “EXHIBIT IS RESISTING”, and the message says something like “I guess you have finished the game, look at this site over here for updates”.

I’m putting this online so that when someone Googles for “Groundhog Life ending” or “how to finish Groundhog Life”, they will find this page, and know that if they want to do that, they’d better start sending tithes to the Strategies for Engineered Negligible Senescence foundation.

P.S.: A review and advice to game designers

Groundhog Life is actually a cute game. I like how it takes a bit of strategizing to maximize some things.

But by god, please, if you make a game, either make it obvious it’s unbeatable, or make it beatable with some indicator of progress. And if you do decide to make your game beatable, please make it beatable for humans in their current meat shells.

2018-09-12 - Review heuristic: Call out bad code

Code health tradeoffs in larger codebases

When people program, they often need to make tradeoffs between what will fix the current problem quickly, and what will make for a healthy codebase. Examples of such a tradeoff is:

I found a function which does almost what I want, but not quite. Do I wait for its maintainer to let me refactor it so I can reuse it, or do I just copy-paste? Or - if it’s just a 5-line chunk, do I extract it into a function if it will require a bunch of boilerplate (maybe it would necessiate adding a new module)?

It’s often a question of “do I pay the bigger upfront cost now, or do I make future-me front it”. These days I often work in a really big codebase, where there ends up being a bunch of those.

My review tip for copy-pasted code

When you review someone’s code that adds similar technical debt, you might not want to force the author to go and dig in 4 files just to extract out a function. It might frustrate them. And also, often it’s really not the best thing to do. If you really only duplicate the same 5-line chunk in two places, and it’s not often changed and not tricky, it might really be less costly to copy it than to agressively share such code.

So the request I often give in code reviews is: “if you duplicate code, add a TODO that the code is duplicated” (preferably to both copies).

This way, you allow the reviewer to quickly go along their day. But also you leave a “hey, this is a known bit of technical debt” affordance in the code.

When someone ends up copy-pasting the same code a third time, you will be much more likely to look and say “hey time to extract a function, there is this TODO which says it’s not the first time we’re doing this”.

General heuristic: “feel the pain”

There is a more general heuristic, which I use, that I call “feel the pain”. The heuristic is that bad things should be obviously painfully bad. Other instances of “feel the pain” are:

  • Let’s say someone breaks the contract of your Frobnicate RPC and sometimes doesn’t pass a required parameter foo, and you need to fix your service to accept that. Fine. But don’t do it like this:

    void HandleFrobnicateRPC(const string& foo, const string& bar) {
      if (foo.empty()) {
        foo = ComputeDefaultFoo(bar);
      }
      ...
    }

    Do it like this:

    void HandleFrobnicateRPC(const string& foo, const string& bar) {
      if (foo.empty()) {
        // NOTE: As of 2018-09-12, the Bazinator service calls Frobnicate with
        // an empty 'foo'. The Frobnicate service cannot be easily fixed to pass
        // the 'foo' itself, because it does not currently have access to the
        // backend which can find the right foo for the bar. If the bar has
        // multiple associated foos, this will only return the last written foo.
        // Other clients SHOULD NOT rely on this.
        foo = ComputeDefaultFoo(bar);
      }
      ...
    }
    Why? Because that way, people are less likely to build more hacks on top of this hack, because there is a long paragraph full of scary words.
  • Let’s say that you inherited 1 million LOC from someone in a hurry, and at some point, they made a misguided architectural decision that makes your code clunky and hard to understand. Create a central bug for this in your bug tracking system, and whenever you write new code that would be made better by fixing the bug, add a note like:

    // TODO(agentydragon): Once we resolve b/12345, we'll be able to replace the
    // Frobnicator with a mock for tests, so our tests won't need such
    // complicated fixtures.
    Why? Because that way once you get around to fixing b/12345, you will be able to grep all places where this hurt some code, and fix them one by one. Also, let’s say some kind soul needs to change this code 2 years after you’re done with it, and finds that TODO. (That person might be you.) When they see this TODO, they might go “hmmm, that bug number looks quite low. aha, it’s been filed 2 years back, and it’s fixed now. yay! that means that I can fix this now and the diff for my new feature will be about 20% less horrible!”
  • Let’s say your code processes two different kinds of things, which both happen to be sort-of-strings (indulge me for a second and assume your code does not use strong types for such things). Think “URLs and street addresses”. For some hacky reason, which you hope to get rid of at some point, you are computing one from the other. What I would do in that case is make that code obviously painful and horrible using devices like variable and function names and type aliases. Not like this:

    string GetResult(const string& input) {
      return UrlEncode(input + "-autogenerated");
    }

    More like this:

    using StreetAddress = string;
    using Url = string;
    
    // Long and verbose comment about why this is necessary and what it should be
    // replaced with and when.
    Url BuildFallbackUrlFromStreetAddress(const string& address) {
      return UrlEncode(address + "-autogenerated");
    }

Even generaler heuristic: “Call out problems”

There is actually an even more general heuristic than this, which is “call out problems”. I also use it in other contexts.

  • Let’s say I am writing a design document, and I notice that I did not actually verify some assumption that I’m making, let’s say, “when a customer frobnicates a Foo without also having a Bar, Frobnicator service will not give them cake”.

    When I notice that and don’t have time to immediately verify it, I’ll openly say, “I believe that when …, then … happens, but did not verify that.” This is good for when your future-self might be going over your notes later, and, reading that doc, starts assuming that the doc is an authoritative source on the particularities of customers getting cake from the Frobnicator service.

    Same about your colleagues. If you say “I did not verify this”, someone who has nagging doubts might be much more likely to say “hey I’m not sure because I’m a human and I forget but I think I got some cake last month when I tried a different thing”, instead of thinking “huh. so he says Frobnicator service does not give cake in this case. I guess they changed it or I don’t remember it correctly.”.

  • Let’s say that I’m talking with someone and they raise a counterpoint to my preferred opinion that I never considered yet. Instead of immediately rushing to defend myself, I sometimes try to instead take in the new thing, and sit there for a bit with the dissonance (“but but but I want to be right so this thing must be wroooong aaaaaaaah”, or maybe “but but but I don’t want to have to redo this 3k line change that I love aaaaaarrrhh”). And instead of “Hmm, but your proposal would not address the …insert ad-lib…”, say, “Huh. I didn’t think of that yet. I’ll need to think about that.”

“Call out problems” feels sort of close to non-violent communication. I feel much less like openly communicating problems if it feels like the environment will hurt me if I do that. That happens to me with some strong personalities, or with people who (probably mostly unknowingly) trigger my sense of “argh I’m being bullied I want to curl up in a corner”. On the other hand, I usually try to call out problems more often than people around me, because I want to nudge culture towards cooperation. (Google culture is pretty blameless, so I don’t feel I’m acting against my interests.)

2018-09-11 - Trying "Things to learn" and "Documented systems"

It’s been a long silence for me on this homepage. Stuff has been happening, but somehow I didn’t find the time to write much.

I’m trying out a new thing. I have a lot of stuff I want to learn some day, but I don’t have the time to learn all of it (and often I also don’t have the leftover energy to do personal-development type stuff, but that is another problem). I’ve had a bunch of systems to remember the interesting things I want to learn - a file on my disk, then a more complex file on my disk, then my laptop crashed, then Google Keep.

So the new thing I’m trying is that I’m adding a new page here called Things to learn. When I find a new thing I want to deeply understand some day, I write it into the list. And when I (some day) feel like diving into a thing, I will pick one up from the list, spend a bunch of time learning it, and then I’ll write a thing, put it on my website and link it from there.

Why this might be good:

  • I won’t hopefully end up forgetting and then relearning the same stuff.
  • Writing something down makes it easier to spot confusion or weak spots in understanding. (Maybe it’s because I spend a lot of time reviewing code. Seeing something written in monospace font makes me go like “huh I’m not sure please write a test”.)
  • I will produce stuff :)

Let’s see how it goes.

Documented systems

Oh by the way, there is a more general thing I’ve been trying which I think might be useful for me.

So CFAR teaches this thing they call “systematization”. (CFAR - Putting Names on Things ™) Examples are:

  • Having your underwear in the top shelf, then the socks, then shorts, etc., and keeping it that way.
  • A checklist you follow when you need to pack up for a flight.
  • Putting all your appointments and other fixed commitments into Google Calendar.

Systems are useful, because they standardize things. Preparing a flight checklist once and then following it 10 times is easier than figuring out if there’s anything important you’re forgetting 10 times at different occassions.

I have a few systems. They have come to be mostly “on their own”, and I might not remember the reason they turned out the way they are.

I want to try making my systems explicit - by writing down a documentation for what each system looks like, what problems does it solve, and such. I want that because:

  • It makes sure the system actually is there for something. This prevents a failure mode I’ve been in after my CFAR workshop, which I once called “cargo cult rationality”. It’s running around beating at random things with CFAR techniques, trying to be a great and conscientious rationalist. (I guess “cargo cult rationality” is also a thing worth writing about some day…)
  • It stores the system out of my mind. For example, I have a system for which things to have in my backpack and where. It tends to deteriorate, and when the chaos threatens to overwhelm my backpack, I can just refer to the explicit description of what goes where, and maybe update it if needed. I don’t have to solve the problem of “figure out the optimal things to put into my backpack and where to put them” every time it gets too messy.
  • It enables debugging.

The way I think of it right now is to have a “source code for my systems”, sort of. Right now I have a like 5-page Google doc with a mix of where things go in my apartment, how to pack for things, and where things go in my backpack, and the motivation and open problems for each.

2018-03-24 - When I use my touchpad to scroll and then press Ctrl, Chrome starts zooming in/out. How to fix that?

This has been plaguing me for a few days (I just got a new Lenovo X1 Yoga laptop), and I think I now figured it out. The Synaptics touchpad driver has a CoastingSpeed option (see man 4 synaptics).

The issue is that when I start two-finger scrolling on a webpage, the driver interprets that to mean “oh and when I take my fingers off the touchpad, please continue scrolling for a few more seconds in the same direction, while slowing down until you stop scrolling”.

Guess what? When you press Ctrl in Chrome and the touchpad driver keeps sending the “ooh we’re scrolling!” message, Chrome starts changing the font size, which is what “Ctrl + scroll” does.

Quoting from the manual:

Your finger needs to produce this many scrolls per second in order to start coasting. The default is 20 which should prevent you from starting coasting unintentionally. 0 disables coasting. Property: “Synaptics Coasting Speed”

I found a command at the Ubuntu community wiki article about Synaptics touchpads which disables this: synclient CoastingSpeed=0. But I guess that won’t stay between restarts.

I’ll add this to a new file in /etc/X11/xorg.conf.d/99-custom.conf:

Section "InputClass"
  # Disable annoying "zoom after two-finger scroll" in Chrome.
  Identifier "touchpad disable coasting"
  MatchDriver "synaptics"
  Option "CoastingSpeed" "0"
EndSection

And I’ll report back if that doesn’t work. (So if this text is still here, you can assume it did and I was too lazy to update this post :p)

2018-03-21 - Triage

I am tired and feel like I shouldn’t go to sleep yet. The Soylent thing has been working only very very slowly. I assume the first few days were just losing the contents of my bowels and now I just want to keep it up. Maybe in the hope that it will remove the habit of snacking when I feel stressed/bad.

The thing about feeling stressed at work has gotten a little bit better. But somehow I don’t feel that much like I’m winning.

Tomorrow a pretty useful thing would be to wake up reasonably early, then ~8 hours of work. I could really use some emotional support. Something’s wrong, actually a bunch of things feel wrong. I feel lonely. I don’t want to be fat. Work sucks and looks like my attempts to hoist myself into an AI safety, or at least AI-related position might fall flat. I might have reached beyond what I am currently good enough for.

I guess the last part feels pretty close to it. Work sucks. If I could do anything with my life, I would do X. Solve for X.

My feelings about it are, … I feel like I kind of grew up with the implicit assumption that work matters. Like, when you are the best at school or at work, people will like you and you will be happy. I want to feel, …, okay? loved? like, I want to cry about how hard and painful things are. Speaking of which, dental pain sucks.

So what’s so painful. First answer is “the fact that I feel I don’t have anyone to cry to”. (At this time. Growth mindset I guess.) I guess compared with that the other things which come up are much lesser. Actually maybe not. I also feel that I have no idea where I’m running, but I’m running there as fast as I can. And stopping where I am, or even the entire idea of stopping, feels dangerous and scary and I don’t want that.

Huh. It would be pretty funny if the function of snacking was to make this cluster of things not hurt. On the other hand, I might still be in the period where going off SSRI’s can do funny chemical things to your head, so there’s that. I guess there might be some fancy antidepressant I could start on to make me itch less right now, but would I want this to stop itching? Maybe not medicating it and not trying to shut it down might be good signal to do something differently…

With that off my chest, it’s still almost midnight and I feel like there are things I should be doing tomorrow. I have a pretty good idea of work things that need doing.

Things on my mind are:

  • Work on my master’s thesis.
  • Check that my mass transit card in ZRH still works (been here a year, it might run out).
  • Buy batteries for my bank’s card reader 2FA machine.

Feeling of having to come up with more stuff.

  • Errrr…

  • I guess, I’m still fat, what do I do about it? Well, that feels kind of forced…
  • I don’t really want to do anything exercise-typey tomorrow. I even have a semi-good excuse for why not to, my ankle is still swollen.
  • But I feel that makes me bad.

Huh. Does it? It feels like it makes me bad, though S2 would publicly say it doesn’t. I also feel tired so probably not gonna IDC on that… Bookmark I guess.

I’m probably not going to reach a point of “yeah I have a plan for tomorrow and it’s a plan which totally resonates”, because I’m pretty tired.

Okay.

Let’s also put some things into Complice. Record weight, eat just Soylent. (Hmm. My calendar reminders are also getting a bit unwieldy. Maybe cancel some of them. Or reevaluate why they’re there. Or start behaving by them…?)

Get the goddamn batteries. And while I’m getting the goddamn batteries, also get some (goddamn) laundry detergent. And check out what other things I’m missing. Lowest-effort way to do that would be coop’s delivery service to the Google office. Yeah, sure, that sounds good.

My room is again slowly becoming a mess. That felt good fixing last time, let’s add that.

Feeling of having to do more.

Okay, when I’m home, I’m going to try to write some Python code that will run in Kubernetes on Google’s cloud to download a dump of Wikipedia for my master’s thesis. Oh, also, I might be able to download it in chunks so it doesn’t have to be loaded into the backing store (probably some kind of BigTable or whatever) in a single thread.

Actually let’s change around my Complice goals, too.

I should also make plans for Easter break. Not sure about what’s the deliverable for that. There’s a bunch of ways I could spend Easter. Baseline, lounging around in Prague chatting with friends. Working intensely on my master’s thesis. (That sounds good in some way.)

Triage done? Argh doesn’t feel entirely like it. I should also make some better plans for one of my partners visiting Zurich.

Itch. But well, I guess this triage will do. The parts which are most important on it are keeping on track with not overeating or snacking, and making some progress on the thesis.

Part of me feels like this is just not enough. Just getting that one Kubernetes script done in one day? Hah, don’t make me laugh. At this rate, you’ll be stumbling around at roughly the same spot in the thesis until time runs out.

Oh, and also, I want to some day go and implement a bunch of ML papers so I can learn TensorFlow and get the confidence to say “I can write AI”. That might actually have higher priority than the master’s thesis, if I were to only care about getting a job in AI.

Sigh. 3, 2, 1, chaaaaaaaarge, and let’s go to sleep. And if we can’t, maybe we can try to probe this “nothing is enough” thing.

2018-03-15 - Against goals

First off, it’s morning so I want to plan out today. An unexpected thing that happened yesterday was misstepping on my run down the stairs when I was going to work, and spraining my ankle. My right ankle, in which I had arthroscopic surgery some years ago. So I had to go to see (another) doctor, and probably will be working from home until the swelling stops. Hopefully it’s just a simple sprain and will be alright in a couple of weeks.

Because I had been home and not at work, I didn’t have Joylent available - I just grabbed the ~1/4th a packet I had at home for breakfast, and then when I came back from having myself drilled in the mouth and touched on the legs, I had been hungry. And I ended up just very quickly cooking whatever was in the kitchen, which was a big can of beans from Denner, 5 eggs and a packet of Chinese noodles. (Since I switched to not cooking and going with Joylent instead, my kitchen is mostly free of any ingredients of my own…) I munched all of that down very quickly, and then felt bad, because my stomach was disturbed and I felt that I had slipped into bad eating habits. I think it was the beans - they were not very good, predictably. When I started cooking the stuff, I did not have much agency, and had the opposite of reflection and mindfulness. I had entered some mode like “gaah eat all the food”. It was lucky for me to not have much actual food at hand, otherwise I might have eaten much more. I actually think I still was under the 2000 kcal I’m getting daily from the Joylent.

I don’t really know what to do next time. I guess something like a TAP like “omg want food → remember to breathe and not eat everything in sight”. Doing mindful eating on the meal would probably also stop it.

Rationality Zurich went fine yesterday. Just 3 people, but we had a nice conversation about an alternative system of self-development brought up by my roommate. My summarization of it is:

Goals are pleasant when you meet them, but painful if you don’t. If you tell yourself “today I will run a mile” and then you don’t, you get an “ow”. The “ow” makes you feel bad, and so the consequence of missing the goal is is feeling bad about yourself for a while. If you can stay on a streak of successfully doing all the things you commit to doing, you will ride a nice wave of “yay I’m doing all the things and I’m doing well”. But miss once, and now you’re a bad bad person (ow) and if you’re like me, on a deep level, you just want to curl up and cry.

Also, my goals are sometimes about “forcing myself to do things good for the long-term, even if they are aversive in the short-term”. That can feel like the part of me which set the goal is grabbing control of everything and dragging along all parts which might be protesting, which is painful.

An alternative is looking at self-development as a process. In that process, you do not set goals which you have to achieve or it’s bad. You don’t try to create a master plan with 34 steps that will perfectly fix everything if you follow them perfectly. Instead, you do small things in the now which are available to you, things which you want to do (or might enjoy doing but aren’t sure yet) that will bring you a very short distance in the general direction of where you want to be. “Where you want to be” might also best be thought of as kind of an emotional “this is who I really am, this is what is really important to me” - not a S2-type explicit list of SMART goals like “I want to weight <= 90 kg by 2019-01-01”.

I really like some things about this view. It’s comparatively very non-violent, and it natually allows for “okay, so a year ago I thought I wanted to be more fit, and I started swimming because I like it, and I met this person and talked with them and changed my goals, so now I want something a bit different”, and you can change what you are “aiming for” (though “aiming for” in a very weak sense, more like “what kind of thing would feel right”) without feeling you’re betraying an earlier commitment.

On the other thing, parts of me seems to want some enforcement device - like the pain you get from missing a goal. Like for some reason I don’t want to stop feeling bad if I e.g. overeat. Maybe a way to make this part feel better about it would be building some self-trust, or what the internal family systems model calls “Self-leadership”. Having some Self which makes sure that parts get along without being violent at each other, and which makes sure that everyone’s needs are met and that parts don’t enter prolonged conflicts. Like, part of me wants to make sure I do get fit, and it’s afraid that if it lets punishing me for not getting fit, I will not get fit.

So, as for today. I’m staying home to nurse my ankle and having a MRI and a chat with a friend in the evening. My plan today is to go on one container of Soylent. I should probably also add another luggage to my flight home.

Part of me feels like this is “a bit too little”. Like “I should also argh be finishing this master’s thesis and argh getting fitter”.

Well, actually I’m doing really good so far. I feel good about the new system/the new process I’m putting into place. Writing about how yesterday went and thinking about the things I will do today felt nice, and I am now not in traps in which I used to be (e.g., the “feel bad → overeat” trap).

I just realized there’s one trap which I haven’t mentioned here yet, and maybe it’s one for which I don’t yet know how would I avoid it long-term. It’s the trap of the work environment pressuring me into acting not fully authentically in it.

Say that I am feeling stressed because there’s too much noise in my office and it hurts and I stayed up all night because I was playing Civilization 5. And what I really want at this point is to go get some sleep.

But it’s work, and if you are not at your post without explanation, your boss will reproach you for that.

But if you tell your boss “hey, sorry, I stayed up all night playing Civilization 5 and I feel really bad about it and I just want to sleep please”, that costs you social points. Because you’re socially-supposed to be a strong independent adult, and strong independent adults are not fragile. And also, you don’t want to show how fragile you are, because you have already had your fragility abused by others plenty of times.

So (barring the opportunity to actually get some sleep), you stay at your post, and you feel bad about yourself, and you just want everyone in your open space to shut up, but you can’t, because they’re allowed to talk at their work place, so aaaaaaaa :’(

Google’s research into effective teams identified this attribute called “psychological safety”, which seems to predict lots of good things, and it seems to me like the belief that it’s okay to make mistakes, that you will not be personally-judged for what you do, that you are not on thin ice, that you are free to be yourself here. I’m not sure if it’s supposed to be mostly work-related - i.e., “it’s okay to break the build for a few days and we won’t be mad at you”. What I think would make me feel better at work and more free to be authentic (and also like it more, because I would not feel forced into putting up a performance of a solid worker drone that I actually am not) would be a kind of “psychological safety” less about the content of my work and more about “it’s okay to be fragile, it’s okay to be disturbed by people talking a lot, it’s okay to cry if you’re overwhelmed”.

Feeling psychologically unsafe is also kind of self-perpetuating. If you don’t feel safe to e.g. express an overwhelming sadness when you feel you’ve done something wrong, and hence you don’t do it, you will use it later as more evidence that you are not psychologically safe here.

Maybe if my current work environment is actually supportive of everything like that and most of my fears/expectations-of-judgement are from this kind of self-driven feedback loop, some CoZE-type experiments could help. Like, maybe when I tell my boss I’m feeling bad, don’t say it while wearing the mask of “I’m an efficient worker and emotions are my slaves”, and instead let it drop and shed a few tears or let my voice break. Meh. Probably actually something weaker than that. This would already feel unsafe.

There’s a thought lingering in my head about the “think of it as a process” thesis. Maybe things which you have to force yourself into doing (by way of e.g., Complice or calendar reminders or willpower or what not) are not really worth it. Because being forced into something hurts. And maybe the thing to do instead is to start with where I am, and making progress through a sequence of comfortable expansions at the margins, all of which feel good and not forced and don’t make me feel bad if I don’t end up doing them.

2018-03-14 - Murphy-jitsu for today

An experiment in writing out and publishing my Murphy-jitsu for today. I have put this in as a reminder for the last ~5 days. The implementation so far has been just “grab a tablet and plan out the day, without real Murphy-jitsu”. Let’s see what happens if I give it some more structure.

What am I planning to do today?

  • I want to eat just 1 packet of Joylent today.
  • I have to go to the dentist.
  • I am organizing a Rationality Zurich meetup tonight.

I need to remember around 13:00 that I have the dental appontment, and to go home by ~18:00 so I am around by the time people start appearing. Let’s set an alarm at 13:00 and 18:00. Done.

The way eating just 1 packet of Joylent might go wrong is:

I feel frustrated and tired and depresssed sitting at my desk, and I default to going for a snack.

What has helped me avoid such situations the last ~5 days was instead going to a sleep pod and having an hour or so of sleep.

I feel annoyed by the feeling of hunger, and also I have slight heartburn for some reason. It would be nice to solve both of those.

Yesterday, I decided to work on implementing a new system. Let this be one step. But still, there’s things which I am not working on towards today. Like maybe getting some exercise to burn off more calories, and I am also not doing anything about my master’s thesis. Part of me feels a bit annoyed, but I think it’s actually fine that I’m not doing anything about those things today. I have a full-time job, a dentist appointment and a meetup in the evening.

I feel that there’s more I could be doing as the current organizer of Rationality Zurich. Maybe there needs to be some soul-searching. I currently don’t actively care as much about rationality-as-actively-trying-to-believe-true-things. Good things I like are tribe-type feelings and what could help could be accountability and goal-setting and stuff. However, those things are pretty different from epistemic-rationality things some rationalists do, like explicitly betting on beliefs. After I arrive home, I could see if I can come up with some cool thing people could do at today’s meetup.

Actually a good thing would be building a scaffolding of “you can always do better than you are doing and that’s a thing to celebrate”.

So, plan for today:

  • Go to work, skip Milliway’s (name of cafe at Google’s ZRH-BRA-110 site where I work), sit at desk, make some Joylent, break fast.
  • I will count how much Joylent is there left in my Joylent box, and probably order more.
  • If I feel overwhelmed and need some quiet, go to a nap room and have a nap.
  • What do I plan to work on today, actually…?
    • There is a task that I could get fully handed off to me from my teammate, and when that’s done, that will give me a nice chunk of useful work to do.
  • If I notice I’m working on some refactoring, I’ll go sit on a couch and think about whether there’s something more useful I could be doing.
    • There’s at least one minor change I could make in another teammate’s project.
  • In the afternoon, I’m going to the dentist.
  • At 18:00, I am leaving work to go back home.
  • Before the Rationality Zurich meetup, I’ll unwind and think about whether there’s some cool thing we could be doing today.

Intentions are entered into Complice, and I can look over them in the evening to see how things went.

2018-03-13 - I need a new system

It’s now March 2018. I have been working at Google for a year. A few days after I started, my personal laptop broke, along with all my meticulously tuned personal infrastructure. I have procrastinated on getting a new one, mostly because I hoped I would fix it myself, or because I did not want to make a big purchase like that.

There’s a lot of problems that keep bugging me and that I need to solve, and after that’s done and my head stops screaming bloody anxiety at me, there’s aspirations. I feel that I need a strategy. It’s useful to take a step back to think about what things are important, what’s working for me and what’s not working, and such. Over the last year I have had a few times where I picked up a piece of paper and started scribbling some strategical stuff on it, but it was always spare moments and not very connected to other such times. I would always start from scratch.

That’s bad. I am obese and need to change that, and changing a thing like that can’t be done by getting a spark of inspiration one day, running on an agenty high for 10 hours, and then it’s fixed. I weigh 124 kg, which is very near my lifelong maximum. The Internet says that you lose 1 pound of fat by burning 3500 kcal (of course, not a figure to take seriously, goodness, I’m just doing a Fermi calculation here, leave me alone), so to get to my optimal weight of let’s-say-78-kg, I’d need to lose 353 500 kcal. The last 5 days I’ve been trying to attack the snacking habits through which I balooned to this weight by eating just a Soylent packet a day. A Soylent packet is 2082 kcal and my basal metabolic rate is 2300 kcal. At this rate, I would get down to 78 kg in… 4.4 years :/ (And that’s not accounting for the fact that BMR decreases the with weight. But on the other hand, I am not completely sessile.)

A goal like this needs some system for coming back to the drawing board every now and then, learning from which things work and which don’t, safety nets for not losing hope and determination if I inevitably fall short at some point. And of course there’s other things in which I could use more wisdom/strategy.

For example, at work. A thing which often happens is that I spend most of the day kind of switching between not-very-useful tasks, like some refactorings or minor features, and feel very frustrated when I get blocked. And I don’t often take a moment to step back to prioritize, and I recognize that if I want to optimize for promotions and recognition (which I do want, among other things), I have gotten myself into a trap.

Or, happiness - optimizing for being happy, being with people I love.

And when things I want conflict, without the opportunity to “detach” from the conflicted parts and allow for some higher-level strategy or prioritization, I just burn cycles feeling bad because of something I also do. Example: I want to move to the Bay, because I think I’ll like the rationalist and furry communities there, but I also feel scared of looking for a new team within Google or scoping for options outside. I want to work in AI safety (part of it is probably about feeling it’s a super high-prestige thing to do), but I also want to be rich and have an upwards career trajectory. And such stuff.

And often, when I feel bad about something, I find myself walking through some conflict I have walked through many times before. Maybe I have walked through that conflict before even with a piece of paper and doing some kind of exercise to reduce internal conflict (like compassion with parts or internal double crux) but somehow that piece of paper is never anywhere to be found.

So, I want a new system for strategical stuff and I want to turn it into a kind of keystone habit which I have. Let this post be a commitment that I want to flesh this out. I’m setting up a weekly 2-hour goal in Google Calendar called “Systems Maintenance”.

What I want from the system

I’ll try to put into words what I want from this system.

I want the system to align my short-term wants (e.g., “I want a cupcake”) with my long-term goals (“I want to lose weight”).

I want the system to track the really important things. I don’t want the system to track things just for the sake of tracking things, or just for the sake of “getting good-boy points for doing an agenty-looking thing”.

If, on reflection, it turns out that a thing that I am doing because of the system is a thing I don’t really want to be doing, then sometimes that will be a fault of the system for picking that thing - not of me for not doing it.

The system is not a system for losing weight or for tracking work.

Some specific things that are bugging me at this time

Here’s a few candidates for things the system might, but also might not lead to me making some progress on. Here, I am deliberately using non-commital language. I am not going to say that I absolutely have to do something. I have found that commitment-mechanism-bombs are sometimes self-blackmail and end up to me causing violence to myself.

But there’s a few ideas for things which often bug me. They do often bug me now, but that does not necessarily mean that dealing with them directly on their own terms is a good idea. Maybe some of them point at problems I actually on reflection want to address. Maybe some of them are distractions, to which the correct solution might be “just stop worrying about it” or “get some fancy antidepressant / do a mind hack to realize those things are not important”.

  • Weight.
  • Unfinished master’s thesis.
  • I want a “feeling that I’m home” - a feeling like “I am safe, I won’t be hurt, things are fine and not fragile, I don’t have to try hard to fight off bad things”. This one feels important.
  • More generally, long-term non-depressed mood.
  • Stress at work. “I have no idea what’s going on higher-level. I am not in control. I feel like a small gear/pawn in a machine.”
  • Feelings of being forced into things by myself.
  • On the other hand, there is a specific thing which I’ve felt the last few days (though I’ve not always been feeling all that well), and which is associated with happiness and also productivity: something like “I can do this”, “things are actually okay”, “I am doing a good job”. “I have committed to a thing and look, I am actually making progress on it.”

There’s also a few aspirational things in mind, which might be candidate goals, but might also be distractions which should be abandoned or shelved. Actually, now that I think about it, they’re mostly “maybe I want to work in AI safety research” and “maybe I want to do some serious EA-planning”. Right now, I’m mostly feeling like setting those aside and focusing on getting myself in order and feeling good without trying to string on specific goals like that.

Sidenote: I don’t think I want to be religious in a certain sense

Relatedly, I’ve gotten somehow less certain about EA stuff - in particular, the role that I want it to play in my life. I have been a religious effective altruist (for a wide sociological take on religion). Independently of whether or not do I want to continue or discontinue some EA-type behaviors (like identifying as an EA, going to EA/rationality meetups, etc.), it’s not healthy to be too identified with a particular belief system.

In my understanding, religions are community plus belief system plus value system. Hang out in the community, and you’re prone to soak up all the rest. And you may see your own (possibly implicit) value system and belief system come into conflict with that of the community. And if you don’t want to leave the community, maybe because you by now know few people outside of the in-group and because you (like me) are deeply pained by loneliness, the part of you which wants to do the right in-group signalling is going to fight the parts of you which want something else.

Say that you identify as an EA and a rationalist and to get social points, the right thing to say is “I want to work on AI safety in the Bay Area”. That’s called a load-bearing belief by analogy with a load-bearing wall: if it comes down, you can lose a lot.

And earlier this year, largely due to talking with a person highly critical of rationality/EA, I have become worried of the fact that I apparently have load-bearing beliefs about EA and rationality. Note that a belief being load-bearing does not imply that it’s false. (Though after reading The Elephant in the Brain, I wouldn’t be surprised if there were some argument for why group-cohesion-beliefs would tend to be outlandish, honest-costly-signalling-something.) So I have become concerned that I might be acting out some beliefs because they’re load-bearing for my need for community and acceptance. I think what’s warranted is a gentle de-identification from the community, by mixing with more people who are not in it and diversifying, and a kind of retracing of my steps in how I came to do EA things.

If I remember correctly, they came mostly from moments when I expanded my empathy over the suffering of all things, and wanted to make things okay, and I expect I will still prefer to try to make the world better on reexamination. But a sort of scary thing is that I think it would feel bad if I came to discover I don’t really care about making the world better.

On the other hand, the general form of this reasoning is: “Huh. Maybe I don’t actually want X. And the thought ‘Maybe I don’t actually want X’ makes me feel bad. That’s a reason to re-examine whether I want X.” Substituting for “X” anything I care about will have the effect of making me doubt whether I actually do, and I’ve had this particular security hole exploited by the said person-critical-of-rationality/EA.

Something for me to maybe think over when I feel like it. But after this writing-it-out, I don’t feel the need for doing anything in particular about it.

Back to the system.

Broad failure modes I want the system to avoid

I know about at least two failure modes I want to avoid.

First, I want to avoid the failure mode where some bump makes the system fall apart.

That is, I want the system to fail gracefully and recover. If part of me wants the system to fail for some reason, the means I should bring things into harmony not by forcing the part to behave, but by accomodating the system to meet the needs of all relevant parts.

Second, I want to avoid the failure mode of “doing all the rationality techniques just so I can get the points for doing self-improvement”.

After attending my CFAR workshop in May 2017, I fell into the second one. I’ve had a document with TAPs that I practiced every day. When I started using Complice, I picked ~5 goals and didn’t revise them, and felt bad when I stopped working on them. I want to put the system in place so I can be awesome. If I am doing self-improvement-type things just because I would feel bad if I would skip them, I have fallen into a trap.

Specific tools that could figure in the system and their failure modes

Every TODO system that grows with time ends in bankrupcy

Something that I guess maybe?? Miranda Dixon-Luinenburg might have remarked on in a document that I have no idea how to Google now (a document discussing productivity tools by some members of the CFAR alumni community) is that everything which looks like a TODO list or inbox is doomed to fail. My Google Inbox, my Google Keep and all the other places which I have used to try to keep track of tactical concerns have over time become full of items which I don’t want to address immediately, but also don’t want to shelve indefinitely. The system’s working memory has to stay constant-size over time. Not keeping the system’s working memory constant-size would lead to the second failure mode, in which obsolete tactical concerns end up dominating, and the system becomes a bother to keep running. The inevitable consequence is that some day, I would declare bankrupcy and start over from scratch.

The thoughts which come to mind upon seeing this are:

  • Zero is the limit of constant-size working memory. Perhaps just regularly reflecting would be better than trying to keep explicit track of all tactical concerns. Maybe my brain will automatically garbage-collect.
  • On the other hand, the principle of Getting Things Done is that the brain does not automatically garbage-collect, and that putting “okay some day I should learn crotcheting” into a TODO list lets the brain be like “okay, now it’s in the TODO list and it won’t get lost, so I can stop thinking about it randomly at 2 in the morning”.
  • A thing which could be good would be explicitly keeping just a few “live tactical concerns”, and keeping everything else in non-working memory. I’m thinking of a DAG growing to the right in time, and keeping a few of the leaf nodes as “working on this”. A thing I tried before my laptop went “lol I won’t turn on now” was storing my collection of personal notes in a git repo, so I could even safely delete from them without losing the things forever.

Writing things down is useful

Yep. It lets reasoning be explicit. When I write down my thoughts, I’m more likely to notice thinking going askew.

Publishing things for other people to look at feels nice and works as a commitment mechanism slash reward signal. On the other hand, things I publish go through my social filter. Probably some balance to strike here.

Too much automation is bad, but I also want the system be my own

As I mentioned, I used to have a whole scaffolding of scripts on my old laptop which would do things like plot my net worth over time, try to mount and unmount an encrypted partition (mostly because of NSFW stuff in it), synchronize Anki decks with a human-readable Git repo of information, and such. And over time, this scaffolding tended to accumulate bugs, like when a service I was relying on changed its API.

I like to program, but time spent programming the system is time not spent being object-level awesome.

I have tried to reduce the custom scaffolding I used (partially out of necessity, because I just didn’t have access without a personal laptop), by supplementing with Keep and such, but I ended up not, for example, keeping up with writing my diary. The more I use general tools, the less will they fit my personal idea of ergonomy.

Also: I’m a programmer and I love programming a nice system. That’s both a blessing and a trap.

Taking up too much time is bad

The system I had in place some time after CFAR accumulated more and more small things, which I would check off every day. The final version was something like: every morning, do a boot-up with a few free-text questions, pick up ~5 Complice daily tasks and maybe put in a few extra Complice goals. Every evening, do a self-improvement round which lasted probably more than 1 hour. It included practicing TAPs, a kind of Murphy-jitsuing around possible problems in my daily routine (a free-form text exercise) and checking in with some of my parts (also free-form text).

I have kind of hard-committed into doing all of this daily, and when it crossed some threshold, I just stopped doing all of it at once.

A way I could have avoided this would be keeping the “mandatory” part constant-time. And also having a looser schedule, in which I could easily spend, say, a whole evening reflecting and improving the routine (as opposed to having very little time and so not feeling like I have the time for meta-stuff, so just chugging along the overly long routine). And by coming into peace with the fact that there are 24 hours in a day, and that if my self-improvement routine takes 2 hours, those are 2 hours less of sleep or fun or whatever.

That feels important. Time is a scarce resource.

It has to be okay to stop doing some things

If I have decided at some point that I want to, say, write a diary entry every day and I end up not doing that, that does not mean that I have failed. If I today decide that something is important, but tomorrow I no longer think it is, that’s okay. I have the right to revise what is important - in fact, revisions are good and welcome.

At one point, I felt that I could change a bunch of bad habits by doing TAPs. But later, the TAP practice routine became very long, but I felt bad about the prospect of just saying “this is no longer the thing to be doing and so I will stop doing that”. A more productive and less conflict-producing way to look at it would be: “I am not feeling like doing this TAP routine, and that’s okay. I deserve rest.”

Tactics are contingent on being useful.

Summary

  • Need a new system
    • System to do good things
    • System to keep me doing well and feeling well
    • System to enact long-term plans
  • Want system to recover from bumps in motivation/mood
  • Specific possible goals:
    • Weight
    • Unfinished master’s thesis
    • Internal conflicts
    • Feeling good
  • Known antipatterns:
    • System becomes a boring chore
    • System bloats over reasonable size
    • System stops tracking what’s the thing to be doing
    • Overly strict commitments
  • Ideas to leverage:
    • Writing
    • Automation, but not too much of it
    • Time is a scarce resource
    • Changes are good

Wall of text ends here

I have an idea of how could a software implementation of a part of the system look like for me - something like a versioned directed graph where nodes would be free text, ideas, tactical priorities, or resources like links to websites, or nodes grouping events or people. It would probably be very fun to implement. However, also time-consuming.

I’ll let my thoughts sit in my mind, and my next action is to sit down in a few days and think some more.

2017-09-19 - Cost of spaced repetition

Spaced repetition is a technique for efficiently memorizing things developed by smart people who noticed that when you get reminded of something after not having seen it for some time, you remember it longer next time. You represent things you want to memorize as two-sided “cards”, which have a prompt on one side (e.g., “Population: Asia”) and the answer on the other side (“4.4 B”). Each card has an interval attached to it, and it starts as a small constant, say, 1 day. When you study a card, you look at the prompt, try to remember the answer, and then flip over the card. If you answered correctly, you exponentially increase the interval, say, multiply it by two. If you answered incorrectly, you return the interval back to the minimum. Different systems have slightly different algorithms.

Spaced repetition is really good for learning large amounts of raw information. I have been using it for about a year now, for example for German words, for studying for my master’s final exam, for country names and flags, and for flags and command line options of tools I use. I use the spaced repetition program Anki.

I have noticed that I sometimes use spaced repetition even if I probably could be doing something more fun, or more productive. It is addictive, sort of like playing Mafia Wars on Facebook in high school was addictive or like checking my stock portfolio every day was addictive - seeing the number of due cards going down has a nice feeling like “I am winning the game” and “I feel smart”.

The cost of Anki addiction is opportunity cost: time I am spending on Anki is time I am not using to do more important things. I want to have a rule of thumb I can use when I consider whether to add stuff to Anki, or whether to keep it there, so I can deliberate: “What is more valuable to me? Having X more hours of free time, or remembering the atomic number of every element?”

Spoiler

How much time does learning one Anki card consume? My rule of thumb is 250 seconds per card over the first year. That means that learning a stack of 100 cards will take about 7 hours.

Read on for how I came up with that.

My process

I will simplify Anki’s algorithm to make the estimate. Let’s assume:

  • A single review takes r = 6 seconds. As of today, I have done on average 542.1 reviews per day and studied on average 54.7 minutes per day, so it works out to about 6 seconds per review.
  • It takes l = 4 reviews to get a card from “learning” to “young” (i.e., from “I have not seen this card or I forgot it” to “I am reviewing it, starting with an interval of 1 day”). I have pulled the number 4 out of my hat.
  • If a card is “young” (i.e., its interval is less than 21 days), I have a 16% chance of getting it wrong and resetting its interval to 1 day (p1 = 0.16). 16% is from my Anki statistics.
  • If a card is “mature” (i.e., its interval is more than 21 days), I have only a 10% chance of getting it wrong (p2 = 0.1).
  • Card intervals multiply by 2 if I get the card right, or drop back to 1 day.

I want to know how much review time will a card cost me over the next 365 days. I start with a card that is unreviewed.

Try 1: Markov chain stationary distribution

I will model it as a Markov chain. The first state is the state of a card being forgotten/in learning, the second state is the state of an interval of 2 days, then 4 days, etc., up to 256 days. (I don’t care about longer intervals for the purpose of 1 year. I’ll pretend a card doesn’t get an interval longer than 256 days.) I will figure out its stationary distribution, and then assume each day I’m paying l × r seconds if I’m in the learning state, r seconds for an interval of 1 day, r/2 for an interval of 2 days, etc. So, I have 8 states.

A Markov chain is only a good model if the long term (where the probability distribution converges to the stationary distribution) accounts for most of the learning cost. This might not necessarily be the case.

I’ll create a transition matrix and get its eigenvector in Octave.

p1 = 0.16;
p2 = 0.1;
M = zeros(8);
M(1:5,1) = p1;
for i = 1:5; M(i,i + 1) = 1 - p1; endfor
M(6:8,1) = p2;
for i = 6:7; M(i,i + 1) = 1 - p2; endfor
M(8,8) = 1 - p2;

I want to find a vector x such that Mx=x and the sum of the components of x is 1:

x = [M' - eye(8); ones(1, 8)] \ [zeros(8, 1); 1];

I got: x = [0.127905; 0.107440; 0.090250; 0.075810; 0.063680; 0.053491; 0.048142; 0.433281]

Now to compute the cost.

r = 6;
w = zeros(1, 8);
w(1) = r * l;
for i = 2:5
  w(i) = (l * r * p1 + (1 - p1) * r) / (2 ** (i - 1));
endfor
for i = 6:8
  w(i) = (l * r * p2 + (1 - p1) * r) / (2 ** (i - 1));
endfor
time_daily = w * x;
disp(time_daily);

That adds up to 3.9 seconds daily.

I noticed the probability mass on the last interval size (0.433) is high. This means that in the stationary distribution, there are many cards with intervals over 256 days, so in the first year of studying a card, the distribution will be more heavily weighted on the smaller intervals.

I decided to try again.

Try 2: Change the assumptions a bit

I’ll slightly change the assumptions of the model. Let’s say that if a card’s interval is x days, it doesn’t mean that it will show up exactly in x days - only that in each following day, it has a 1/x chance of coming up.

Let’s create a matrix of transition probabilities:

p1 = 0.16;
p2 = 0.1;
M = zeros(8);
for i = 1:8;
  p_change = 1 / (2 ** i);
  % Fill in probabilities of reviewing and then forgetting.
  if i <= 5
    M(i,1) = p1 * p_change;
  else
    M(i,1) = p2 * p_change;
  endif
  % Fill in probabilities of reviewing and then getting it right.
  if i < 8
    if i <= 5
      M(i,i+1) = (1 - p1) * p_change;
    else i < 8
      M(i,i+1) = (1 - p2) * p_change;
    endif
    % Fill in probability of staying in the same state.
    M(i,i) = 1 - M(i,1) - M(i,i+1);
  else
    M(i,i) = 1 - M(i,1);
  endif
endfor
% Fix for the first row.
M(1,1) = p1;
M(1,2) = 1 - p1;

We are going to pay for transitioning from state A to a different state B. Transitioning from A to A+1 or from A to 1 costs r seconds, and transitioning from 1 to 2 costs r × l seconds. Let’s create a cost matrix.

r = 6;
l = 4;
C = zeros(8);
for i = 2:8;
  if i < 8
    C(i,i+1) = r;
  endif
  C(i,1) = r;
endfor
C(1,1) = r;
C(1,2) = r * l;

We start with the card in state 1 with probability 1, and we have paid no costs yet. I will represent the costs as a vector of costs paid entering a given state. At the beginning, we have paid nothing.

pd1 = [1 0 0 0 0 0 0 0]';
c1 = [0 0 0 0 0 0 0 0]';

I will want to get the total costs by doing matrix multiplication. After 1 day, the probability distribution will change, and we will incur some costs.

pd2 = M' * pd1;
c2 = (C' \.* M') \* pd1 + c1;

This change is linear, and we will represent the state as a combination of the probability distribution vector and the costs paid so far.

In Octave, I will create a matrix transitioning from one state to another and a vector representing the entire state:

T = [M', zeros(8); M' .* C', eye(8)];
s0 = [1; zeros(7, 1); zeros(8, 1)];

So, after 365 days, we have paid these daily costs:

daily_costs = sum((T**365 * s0)(9:16)) / 365;
disp(daily_costs);

This model gives me 0.32 seconds per day. This is 117.69 seconds per year, of which 58 are spent transitioning from state 1 to state 2. The probability distribution was also heavily skewed towards the higher intervals - 64% of cards were in the last state. That means this model is just overly optimistic; there is no way 60% of cards in the unsimplified algorithm could have an interval this long after just 1 year (they would first have to go through the 128 + 256 days). This tells me this model might be way off and broken.

Try 3: Python

And at this point, I’m like “fuck this, I’m better at Python than at math”. So I wrote a thing in Python:

#!/usr/bin/python2

import random
import numpy

p1 = 0.16
p2 = 0.1
review_time = 6
reviews_to_learn = 4

def simulate_cost_of_card_over_year():
  next_day = 0
  interval = 0
  cost = 0
  while next_day < 365:
    if interval == 0:
      cost += reviews_to_learn * review_time
      interval = 1
    else:
      cost += review_time
      if interval < 21:
        if random.random() < p1:
          interval = 0
        else:
          interval *= 2
      else:
        if random.random() < p2:
          interval = 0
        else:
          interval *= 2
    next_day += interval
  return cost

tries = [simulate_cost_of_card_over_year() for _ in range(1000)]
print numpy.mean(tries)

And I got these results:

30 81.804
365 159.438
3650 252.15
18250 367.38

That tells me that over the first year, I will spend about 0.43 seconds per day reviewing the card. I trust this result more than I trust my previous hacky math.

Why all the estimates are bullshit

At this point, I was thinking about to declare “victory, it’s about 0.43 seconds per day, and let me now also say why exactly the number is bullshit”:

  • Anki actually doesn’t use a constant interval multiplier of 2; it uses 2.5 by default, and it also adjusts the interval as it goes.
  • You can also answer cards as “Easy”, which makes the interval even bigger.
  • The estimate of “it takes 4 tries to learn a new card” was totally made up.

And then I realized I can actually fix the last point, and that it’s probably also the most significant problem - most of the time spend on a given card will be learning it, not reviewing it.

Fixing the reviews per learning constant

Anki says I did ~35k “Again” responses on cards in learning, and ~65k “Good” responses (and a negligible amount of “Easy” responses). This means that on an attempt to answer a card in the learning phase, I have a p=0.62 chance to get it right. I have Anki setup such that a card graduates to reviewing after I get it right 3 times.

Denote e0, e1, e2 the expected number of attempts it will take me to get a card graduated, given that I have successfully answered it the last 0, 1, or 2 times.

We have: e2 = p × 1 + (1-p)× (1 + e0), e1=p× (1 + e2) + (1-p)× (1 + e0), e0 = p× (1 + e1) + (1-p)(1 + e0). Splashing that around a little bit, I get e0 = 1/p + 1/p2 + 1/p3, which means: e0 = 8.44.

So, that entails some corrections.

Correcting for that in the Python program (setting reviews_to_learn = 8.44) yields:

30 135.76992
365 252.52464
3650 364.75824
18250 502.50888

This means 0.69 seconds per day in the first year, and a total of 250 seconds in the first year, and ~2 minutes in the first month.

Corollaries

  • Learning a new keyboard shortcut is worth it if it will save me 0.7 seconds per day over the following year. (Or 250 seconds in total).
  • My German deck, which has 26 241 cards, would take roughly a whooping 1822 hours over the next year. That’s a full 227 workdays.
  • Rai has an Anki problem.

You can find more in the archive.