<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6245476510271728435</id><updated>2026-03-02T13:35:24.488+01:00</updated><category term="grails"/><category term="asp.net mvc"/><category term="groovy"/><category term="unit testing"/><category term=".NET"/><category term="java"/><category term="vue"/><category term="extjs"/><category term="ruby"/><category term="git"/><category term="JSF"/><category term="camel"/><category term="javascript"/><category term="jquery"/><category term="software-development"/><category term="visual studio"/><category term="asp.net"/><category term="nunit"/><category term="webservices"/><category term="AVCHD"/><category term="DynamicData"/><category term="ikvm"/><category term="java 7"/><category term="json"/><category term="plugins"/><category term="poi"/><category term="ruby-on-rails"/><category term="sinatra"/><category term="spring"/><category term="tomcat"/><category term="vue.js"/><category term="vuejs"/><category term="C#"/><category term="Delphi"/><category term="cors"/><category term="eclipse"/><category term="ext-core"/><category term="ffmpeg"/><category term="gitorious"/><category term="gorm"/><category term="hazelcast"/><category term="memcached"/><category term="msbuild"/><category term="php"/><category term="tags"/><category term="ubuntu"/><category term="wtf"/><category term="33rd degree"/><category term="4Developers"/><category term="Agile"/><category term="COM"/><category term="ExP"/><category term="Graylog"/><category term="ICEfaces"/><category term="IDE"/><category term="Lua"/><category term="M2TS"/><category term="MTS"/><category term="Mercurial"/><category term="MyBlog"/><category term="MyFaces"/><category term="NodeMCU"/><category term="PDC09"/><category term="PIPA"/><category term="PostgreSQL"/><category term="SOPA"/><category term="TenThingsIHateWithAPassion"/><category term="WVD"/><category term="amqp"/><category term="api"/><category term="brain dump"/><category term="c# 4.0"/><category term="class library"/><category term="clean-code"/><category term="closures"/><category term="code coverage"/><category term="component"/><category term="conference"/><category term="css"/><category term="cxf"/><category term="devkit"/><category term="documentation"/><category term="dotnetcore"/><category term="driving on empty"/><category term="dynamic"/><category term="easyb"/><category term="esx"/><category term="esxi"/><category term="example"/><category term="express"/><category term="ext.direct"/><category term="faq"/><category term="freepascal"/><category term="functional"/><category term="future"/><category term="fxcop"/><category term="gsp"/><category term="hello-world"/><category term="hibernate"/><category term="history"/><category term="img"/><category term="installation"/><category term="javaee6"/><category term="javamelody"/><category term="joining parts"/><category term="jquery-plugin"/><category term="jruby"/><category term="jtk"/><category term="ldap"/><category term="licensing"/><category term="linux"/><category term="localization"/><category term="mail"/><category term="maven"/><category term="modelbinder"/><category term="mongo"/><category term="multi-tenant"/><category term="mvc controls"/><category term="nhibernate"/><category term="phalanger"/><category term="phpPgAdmin"/><category term="pico"/><category term="polyglot-programming"/><category term="proxy"/><category term="quartz"/><category term="rabbitmq"/><category term="rails"/><category term="rake"/><category term="ratpack"/><category term="re-encoding"/><category term="rest"/><category term="selenium"/><category term="servicemix"/><category term="sfc"/><category term="spark"/><category term="spark-java"/><category term="spock"/><category term="spring.net"/><category term="sql server"/><category term="sts"/><category term="stuff-not-use"/><category term="stylecop"/><category term="subversion"/><category term="teradata"/><category term="testing"/><category term="typescript"/><category term="unity"/><category term="updatemodel"/><category term="vmware"/><category term="vscode"/><category term="warbler"/><category term="web controls"/><title type='text'>Padcom&#39;s blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>310</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-1352061935291284140</id><published>2021-12-15T10:33:00.002+01:00</published><updated>2022-01-19T11:58:27.942+01:00</updated><title type='text'>Principles of software architecture</title><content type='html'>&lt;p&gt;
  Hello folks! Recently, I&#39;ve been doing some consulting for an e-commerce site. During the review it struck me that there are no ground rules there (or anywhere else for that matter) that would guide what the architecture should look like. So I came up with some points myself:
&lt;/p&gt;


&lt;h2&gt;Principles of architecture&lt;/h2&gt;
&lt;p&gt;
  The following describes the principles of the desired state of architecture. Architecture is being viewed in this case not only as the system of interconnected components but as a complete framework for developers, testers, devops and business to know their way around the system.
&lt;/p&gt;

&lt;h3&gt;Ease of development&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow for streamlined and effective use of development resources:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the technologies being used should be widely adopted to allow for easy sourcing of new resources (developers, designers, testers)&lt;/li&gt;
  &lt;li&gt;both backend and frontend tooling should allow for quick turnaround between changing the code and observing the result&lt;/li&gt;
  &lt;li&gt;manual work to get the changes to appear in local development environment should be eliminated&lt;/li&gt;
  &lt;li&gt;all projects should have a unified API for starting the development environment&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Ease of deployment&lt;/h3&gt;
&lt;p&gt;The following principles will allow for uninterrupted delivery of individual changes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;deployment of changes should be automated which includes automated validation of changes as well as pubishing chnaged to production&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Extensibility&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow for continuous development of new features:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the system should obey the law of simple design which dictates that finding the relevant part of the code should be obvious and easy&lt;/li&gt;
  &lt;li&gt;the system should obey the law of extensibility which dictates that changing/adding/removing functionality should be possible without changing parts of the system that are not directly connected to the part being changed/added/removed (derived from the Open/Closed principle)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Maintainability&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow for continuous improvements of existing features:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the system should be and remain maintainable. This means that both development of new functionalities as well as bugfixes should be as easy and as universaly applicable as possible. For instance, the developer shouldn&#39;t worry where to get the data from to reproduce reported errors and how to connect the parts being developed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;High availability&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow to increase the presence of your app on the market:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the system should be able to loose access to parts of it without breaking the user experience. That applies not only to services serving the data (such as the CMS) but also to services serving static resources and custom APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Performance&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow to increase the presence of your app on the market:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the system should be performant enough to consistently serve every page update under 2 seconds. This leaves 25% margin for variation in delivery time due to connection speed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Security&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow to eliminate any potential risks involving unauthorized use of the system thus eliminating losses:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the system should not allow for unauthorized users to perform actions they would normally be allowed to accomplish. That includes both accessing frontend pages as well as backend services. Maintaining access to elements of the system should be easy and performant and shouldn&#39;t overshadow the essential functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Accounting&lt;/h3&gt;
&lt;p&gt;
  The following principles will allow to reason about the undesired behavior:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the system should employ globally tracable logging facilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So there you go - a few rules to guide you when you need to decide if what you&#39;re doing is good or bad.&lt;/p&gt;
&lt;p&gt;
  The point of this list is not only to show what is important but also to prioritize which parts of it are more important than others so you go top to bottom. If your app isn&#39;t a critical one then performance and high availability isn&#39;t all that important. If it&#39;s being used by just 2 people in the entire company and the app is basically a glorified spreadsheet then security and accounting might not be a concern for you. Regardless of the project size its ease of development, maintainability and extensibility are always key points of any architecture.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Have fun!&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/1352061935291284140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/1352061935291284140' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1352061935291284140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1352061935291284140'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2021/12/principles-of-software-architecture.html' title='Principles of software architecture'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-3707639971069989247</id><published>2021-07-10T12:35:00.003+02:00</published><updated>2021-07-10T12:42:32.110+02:00</updated><title type='text'>There is no such thing as free beer - RC link comparison</title><content type='html'>&lt;p&gt;
  Controlling a model in the air is not all that difficult. There are analog systems that use PWM modulation that we all know from the old ages where RC hobby was only available for the very few ones with deep pockets and then there are digital systems like DSM2/DSMX, ACCST, ACCESS, CRSF, ELRS and probably a dosen more that rely on some kind of analog signal modulation (like FLRC, LoRa or others) to send digital information.
&lt;/p&gt;

&lt;p&gt;
You might have heard about the exceptional results of ExpressLRS system that &lt;a href=&quot;https://www.youtube.com/watch?v=dBmTRhgVcyY&quot;&gt;Wezly&lt;/a&gt; got from his long range tests. I mean, going 35km out on 100mW output power is seriously a lot. Even the mighty Ghost from ImmersionRC or Tracer from Team Blacksheep struggled to get past the 30km mark in the real world tests. So what sets ExpressLRS apart? Are those OpenSource guys just better than commercial companies? Is this the end of the world as we know it?
&lt;/p&gt;

&lt;p&gt;
Well, as the title of this post says, there&#39;s no such thing as free beer. Nor is there RF performance that comes for free. Here&#39;s the secret behind ExpressLRS exceptional performance.
&lt;/p&gt;

&lt;p&gt;
All other links, besides ExpressLRS are called by the number of channels they support. For example Crossfire (both 900MHz and 2.4GHz) support up to 12 channels. Sure enough there is prioritization of which channels are being sent most often (that&#39;d be the first 4 channels where control inputs are being transmitted) but all channels are being sent with full resolution. If you come to thing about it that&#39;s a huge waste of bandwidth if you only want to send binary (on/off) information. That can be encoded on just one bit instead of 10 bits which is the usual resolution of channels.
&lt;/p&gt;

&lt;p&gt;
This is exactly what ExpressLRS does - it sends 4 full resolution channels at an extremely high packet rate (500Hz!) but the rest is sent as 1 byte (8 bits) and only conveys if a switch is on or off. That&#39;s the default mode for ExpressLRS and it works great with software such as Betaflight or INAV and for simple setups such as a racing quad or a small flying wing.
&lt;/p&gt;

&lt;p&gt;
There is a second &quot;mode&quot; that you can select when building the firmware that is called &quot;Hybrid switches&quot; in which the 5th channel is a binary switch that is sent with every packet (and that shall be used for controlling arming the quad),then there are  6 channels that can take up to 6 positions (3 bits) and finally there&#39;s the 12th channel which has a 4 bit resolution which amounts to 16 different values being sent.
&lt;/p&gt;

&lt;p&gt;
Yes, you read this right: there are only 4 full resolution, high performance channels in ExpressLRS. This is how the link can have much much much smaller packets than any other system. But that comes at a cost. If you&#39;d like to control, let&#39;s say, a gimbal in 2 or 3 axes you&#39;re not going to be able to do that with ExpressLRS. It just doesn&#39;t have the technical capabilities at the core of the solution that would allow you to do that.
&lt;/p&gt;

&lt;p&gt;
Then there is the telemetry thing...
&lt;/p&gt;

&lt;p&gt;
Telemetry is data being sent from the receiver back to the radio. It can include anything from link statistics, battery voltage to GPS position, altitude, attitude of the craft and many many more. That holds true for everyone - besides ExpressLRS. Sure, the basics, such as the GPS position and link stats are being sent back but that is about it. This, however, further limits the amount of data that needs to be sent back and forth which in turn means ExpressLRS can send less data in the aloted time frame and they can do it a lot slower thus extending the range.
&lt;/p&gt;

&lt;p&gt;
So we know what are the limitation. Who would then use such a crippled RC system? Is it good for anything?
&lt;/p&gt;

&lt;p&gt;
Let&#39;s examine the requirements of a typical racing pilot. First, the faster the response from moving the sticks the better. There is no limit to it. Faster is better. But does a racing pilot need telemetry? No. does one need a gimbal on the quad that goes from zero to 100 in a second? Hello no! What is needed is a reliable channel for arming/disarming and 4 very fast, very accurate channels to control the vehicle. That&#39;s it.
&lt;/p&gt;

&lt;p&gt;
That&#39;s 1:0 for ExpressLRS vs everyone else.
&lt;/p&gt;

&lt;p&gt;
Let&#39;s see what a typical long-range pilot requires to operate a vehicle at 50km+. 4 control channels - check. A way to arm/disarm - check. A way to switch between 4 modes (launch, air, 3D cruise, RTL) - check (although it requires a bit of fiddling around to get it to work with the default setup with binary switches - in the hybrid mode it is quite simple though). And frankly speaking 500Hz update rate is just not that useful. The thing that is usually happening during the flight is that the plane flys itself and the pilot only enters minor course corrections to point the plane where it should go. So even if the packet rate is at about 5Hz it will still be way more than enough.
&lt;/p&gt;

&lt;p&gt;
But if one would like to have a camera that moves around to be able to see if there is anything coming in at the aircraft from any direction, then the 16 position AUX8 is just not good enough.
&lt;/p&gt;

&lt;p&gt;
That&#39;d be 1.5:0.5 for ExpressLRS vs everyone else.
&lt;/p&gt;

&lt;p&gt;
Now let&#39;s go ahead and see what the big boys need. Imagine you&#39;re flying something like a hexacopter, with a gimbal and a lot of other accessories. You&#39;re most probably going to be doing that with the help of some ground station to better see where you are. For that you need telemetry and a control link that can not only send analog stick positions but also commands to the aircraft (most probably using the two-way MAVLink protocol). ExpressLRS is just not capable of any of that.
&lt;/p&gt;

&lt;p&gt;
That&#39;d be 1.5:1.5.
&lt;/p&gt;

&lt;p&gt;
So it all depends on what you need vs what you can live without. If, for example, you&#39;re flying a tiny whoop and just want to have decent range but not a lot of cables and antennas - ELRS has you covered. If you&#39;re racing or freestyling and need the fastest link possible - again ELRS is the way to go. The greay area starts with piloting anything that can be a bit more sophisticated than just doing crazy things around the tree. Planes tend to have much more functionality that sometimes needs more control. This is where ExpressLRS starts to fade and other, full-fledged control links come into play.
&lt;/p&gt;



</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/3707639971069989247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/3707639971069989247' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3707639971069989247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3707639971069989247'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2021/07/there-is-no-such-thing-as-free-beer-rc.html' title='There is no such thing as free beer - RC link comparison'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-816520297336287942</id><published>2021-04-06T12:02:00.000+02:00</published><updated>2021-04-06T12:02:18.153+02:00</updated><title type='text'>Hasura - querying fields conditionally</title><content type='html'>&lt;p&gt;
  As it turns out GraphQL is great :) I know, I know,... it&#39;s an old story but with Hasura sitting on top of PostgreSQL it is a whole different world to explore.
&lt;/p&gt;
&lt;p&gt;
  For example, there might be times where you have some filter that might say &lt;quote&gt;Select variant: &quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;any&quot;&lt;/quote&gt;. Previously it was kinda obvious, that you&#39;d say the values were &lt;code&gt;[ &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, null ]&lt;/code&gt; which resulted in collapsing the expression to an empty object but with the advent of Hasura 2.0 this feature was removed. Are we left with nothing? Hell no!
&lt;/p&gt;

&lt;h2&gt;Conditional expressions&lt;/h2&gt;

&lt;p&gt;
  So let&#39;s say you have a &lt;code&gt;String&lt;/code&gt; field that you want to either query by a value or skip in the &lt;code&gt;WHERE&lt;/code&gt; clausule completely. How would you do that if &lt;code&gt;null&lt;/code&gt; is not traversed to &lt;code&gt;{}&lt;/code&gt;?
&lt;/p&gt;

&lt;p&gt;
  First, let&#39;s make an example and then I&#39;ll exaplain everything in details.
&lt;/p&gt;

&lt;p&gt;
&lt;pre&gt;&lt;code&gt;query GetItems($field: String_comparison_exp!) {
  items({
    where: {
      field: $field
    }
  }) {
    id
    field
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

And the accompanying &lt;code&gt;variables&lt;/code&gt; section to go along with it:

&lt;p&gt;
&lt;pre&gt;&lt;code&gt; { field: value ? { _eq: value } : {} }&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
  So what happened here? First, as you can see we&#39;re not passing the value of &lt;code&gt;$field&lt;/code&gt; anymore. Instead we&#39;re passing a &lt;code&gt;String_comparison_exp&lt;/code&gt;. This is a way of passing the actual expression in variables. Previously, in Hasura &amp;lt;2.0 when a value was &lt;code&gt;null&lt;/code&gt; the actual epxpression evaluated to an empty object (&lt;code&gt;{}&lt;/code&gt;) which in turn evaluates to &lt;code&gt;TRUE&lt;/code&gt; in the SQL being generated. That last part still holds true, but &lt;code&gt;null&lt;/code&gt; is no longer collapsed in Hasura 2.0. Instead you need to do that yourself. There was a ton of issues with people deleting whole content of tables and so they removed this particular functionality.
&lt;/p&gt;

&lt;p&gt;
  Remark: if your field is not of type &lt;code&gt;String&lt;/code&gt; there will be an error telling you what type of &lt;code&gt;expression_exp&lt;/code&gt; you need to use. Just read the effin error message :D.
&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;
  So now you know how to manually do the collapsing and you&#39;re the boss of GraphQL again!
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Happy coding!&lt;/i&gt;&lt;/b/&gt;&lt;/p&gt;
  


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/816520297336287942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/816520297336287942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/816520297336287942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/816520297336287942'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2021/04/hasura-querying-fields-conditionally.html' title='Hasura - querying fields conditionally'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-2121545805384540957</id><published>2020-10-14T15:52:00.003+02:00</published><updated>2020-10-14T16:49:16.800+02:00</updated><title type='text'>Classes and inheritance with Vue CLI-generated Cypress tests</title><content type='html'>&lt;p&gt;This is going to be a quick one but took forever to figure out. Brace yourself!&lt;/p&gt;

&lt;h2&gt;The setup&lt;/h2&gt;

You have a project that is managed by vue-cli and you have end to end tests created with Cypress (all stock!). Now you want to move it to the next level and use wrappers as described in this &lt;a href=&quot;https://www.youtube.com/watch?v=NJpB047yp9s&quot;&gt;tutorial&lt;/a&gt;. 

&lt;h2&gt;The problem&lt;/h2&gt;

&lt;p&gt;When you try to create classes in separate modules the strangest thing happens:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import _typeof from &quot;../../helpers/esm/typeof&quot;;
^
ParseError: &#39;import&#39; and &#39;export&#39; may appear only with &#39;sourceType: module&#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is easy to fix. Just install &lt;code&gt;@cypress/webpack-preprocessor&lt;/code&gt; package and follow the instructions in &lt;code&gt;tests/e2e/plugins/index.js&lt;/code&gt; - it&#39;s all there.&lt;/p&gt;

&lt;p&gt;But the moment you&#39;ll try to use them... all of the sudden &lt;b&gt;no tests are found&lt;/b&gt;.&lt;/p&gt;

&lt;h2&gt;The Solution&lt;/h2&gt;

&lt;p&gt;The actual issue here is transpilation and yes, you&#39;ve guessed it - it has to do with Internet Explorer support. The fix is super easy.&lt;/p&gt;

&lt;p&gt;Go to &lt;code&gt;.browserslistrc&lt;/code&gt; and add the following line at the end of the file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;not ie &gt; 0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And live is good again :) I so hope the masacre called Internet Explorer will be over really soon!&lt;/p&gt;

&lt;b&gt;&lt;i&gt;Happy coding!&lt;/i&gt;&lt;/b&gt;

</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/2121545805384540957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/2121545805384540957' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2121545805384540957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2121545805384540957'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/10/classes-and-inheritance-with-vue-cli.html' title='Classes and inheritance with Vue CLI-generated Cypress tests'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-3469546216398426383</id><published>2020-09-23T18:50:00.000+02:00</published><updated>2020-09-23T18:50:11.916+02:00</updated><title type='text'>ESP3D on SKR 1.4/1.4 Turbo with ESP01S</title><content type='html'>&lt;p&gt;So you have the board. It&#39;s new, shiny and it has this strange looking 8 pin port labeled WiFi? Seriously?! WiFi on that board?&lt;/p&gt;

&lt;p&gt;Yes! And it is quite easy to set it up! Curious? Let&#39;s begin!&lt;/p&gt;

&lt;h3&gt;Installation of required tools&lt;/h3&gt;

&lt;p&gt;For obvious reasons I&#39;ll tell you how to do it on Linux. It may work on MacOS too and I doubt it&#39;ll work on Windows. Linux is my go-to system and I don&#39;t use anything else.&lt;p&gt;
  
&lt;h4&gt;Installing PlatformIO&lt;/h4&gt;

&lt;p&gt;First you need Platformio commandline tools installed. You can find the instruction on PlatformIO website &lt;a href=&quot;https://docs.platformio.org/en/latest/core/installation.html#super-quick-mac-linux&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ve had to symlink the &lt;code&gt;pio&lt;/code&gt; command to &lt;code&gt;~/bin/pio&lt;/code&gt; to have it available without specifying the full path. Your milage might vary.&lt;/p&gt;

&lt;h3&gt;Clone the repository&lt;/h3&gt;

&lt;p&gt;This is quite easy if you already have Git installed. If you don&#39;t have it check out &lt;a href=&quot;https://git-scm.com/book/en/v2/Getting-Started-Installing-Git&quot;&gt;this&lt;/a&gt; site for further information. Once Git is on your system clone the repository by issuing the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone https://github.com/luc-github/ESP3D&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Building&lt;/h3&gt;

&lt;p&gt;This is the coolest part :) There are a few commands that will get you to 100% in no time thanks to PlatformIO:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Erasing EEPROM:
$ pio run -e esp01s_160mhz -t erase

Uploading the firmware:
$ pio run -e esp01s_160mhz -t upload

Uploading files to the SPIFSS
$ pio run -e esp01s_160mhz -t uploadfs&lt;/pre&gt;&lt;/code&gt;

&lt;h3&gt;Configuration of ESP3D&lt;/h3&gt;

&lt;p&gt;Configuring the module is pretty straightforward and described really well on &lt;a href=&quot;https://github.com/luc-github/ESP3D/wiki/Install-Instructions#initial-configuration&quot;&gt;this&lt;/a&gt; page so I won&#39;t duplicate the content. Clicking a link is easy enough :D&lt;/p&gt;

&lt;h3&gt;Configuration of Marlin firmware&lt;/h3&gt;

&lt;p&gt;Now this used to be a royal pain in the neck requiring you to modify framework code which was plain and simple ugly. Luckily enough this is now made super simple!&lt;/p&gt;

&lt;p&gt;Find a place in &lt;code&gt;Configuration.h&lt;/code&gt; that has the following line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/**
 * Select a secondary serial port on the board to use for...
 * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
 */
//#define SERIAL_PORT_2 -1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and change it to look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/**
 * Select a secondary serial port on the board to use for...
 * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
 */
#define SERIAL_PORT_2 3
#define LPC_PINCFG_UART3_P4_28&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;#define LPC_PINCFG_UART3_P4_28&lt;/code&gt; is the newest addition to the LPC1769 core and allows to use the correct pins for the second serial port so that the module can properly communicate with the board.&lt;/p&gt;

&lt;h3&gt;Compiling Marlin&lt;/h3&gt;

&lt;p&gt;Now that we have PlatformIO installed we can build Marlin from command line which I think is super cool and so easy! Switch to the root of the Marlin repository and issue the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pio run -e LPC1769&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And a few moments later... that&#39;s it! You have the latest firmware in &lt;code&gt;.pio/build/LPC1769/firmware.bin&lt;/code&gt;&lt;/p&gt;

&lt;b&gt;&lt;i&gt;Have fun!&lt;/i&gt;&lt;/b&gt;

</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/3469546216398426383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/3469546216398426383' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3469546216398426383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3469546216398426383'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/09/esp3d-on-skr-1414-turbo-with-esp01s.html' title='ESP3D on SKR 1.4/1.4 Turbo with ESP01S'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-3163079174570740168</id><published>2020-06-17T01:22:00.000+02:00</published><updated>2020-06-17T01:22:08.509+02:00</updated><title type='text'>I solved the biggest problem I&#39;ve had recently</title><content type='html'>&lt;p&gt;One of the biggest headaches I&#39;ve had recently was to get a software NLE (non linear video editor) to do friggen frame freezes. I edit videos in such a way that I can explain what I do on the screen which, obviously, sometimes requires to pause the video feed and let the audio do its work.&lt;/p&gt;

&lt;p&gt;Up until yesterday I&#39;ve been using Blender&#39;s F12 (or as you&#39;ll know it Render Frame) feature, then clicking &quot;k&quot; for cut and inserting the image in the place where I needed to do the freeze frame. What a colossal waste of time! And I&#39;ve had that feeling for over two months but couldn&#39;t find a solution for it.&lt;/p&gt;

&lt;p&gt;So I kept on doing it and I kept on searching for alternative software that would allow me to do what I need....&lt;/p&gt;

&lt;h2&gt;The solution&lt;/h2&gt;

&lt;p&gt;Sometimes it is better to look at the tools you already have at hand and learn them in more depth than just start looking for alternatives. This was the case Today with me and Blender. Blender is a fantastic NLE and I dare to say it satisfies now all the needs I&#39;ll ever ever will have. Especially now that I have learned the Shift-K (hard-cut) feature.&lt;/p&gt;

&lt;p&gt;So the thing is there&#39;s a difference between a soft-cut (k) and a hard cut (shift-k). With soft-cut your clip will extend beyond the last frame when you extend it on the timeline. With hard cut it will essentially repeat the last frame which was what I was looking for in Blender for over A FRIGGEN MONTH!!!&lt;/p&gt;

&lt;p&gt;God! I wish someone would have written an article about freezing frames in Blender....&lt;/p&gt;

&lt;p&gt;In the mean time... keep on having fun!&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/3163079174570740168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/3163079174570740168' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3163079174570740168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3163079174570740168'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/06/i-solved-biggest-problem-ive-had.html' title='I solved the biggest problem I&#39;ve had recently'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-1598942123744476409</id><published>2020-03-31T03:44:00.000+02:00</published><updated>2020-03-31T03:44:29.695+02:00</updated><title type='text'>Building a MIDI console with Arduino </title><content type='html'>&lt;p&gt;
I have recently been overwhelmed with what can be done with Audio on Linux. The DAWs, like Ardour, are not only free but also so extremely powerful you can actually do lots with it. I don&#39;t know if it would stand against the big guys but knowing there&#39;s no limitation for tracks, buses and the use of plugins it seems like the sound editing capabilities are only limited by the CPU power. Or are they?
&lt;/p&gt;

&lt;h3&gt;Hardware to be made&lt;/h3&gt;

&lt;p&gt;In point of fact I am not a professional. I did take some piano lessons (my mum was a piano teacher and I was forced to follow in her footsteps for 5 years that I would rather forget) but beyond that and a few years of learning the theory of music I have no idea what I have set out myself to do. So what is it exactly that I&#39;d like to do?
&lt;/p&gt;
&lt;p&gt;
Well, it is not all that difficult. I think it is far more enjoyable to tweak all the knobs in a DAW if you have... welll.. knobs :D Moving them all with a mouse is just such a pain in the ass. So I have decided to make some hardware that will allow me to control the DAW with physical knobs.
&lt;/p&gt;
&lt;p&gt;
Following are some basic ideas that I have that will allow me to complete my mission:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every mixer console has a slider for volume - I need one of those&lt;/li&gt;
&lt;li&gt;Every mixer console has a number of knobs that can be turned from left to right that will then change some parameter in the DAW - configurable. I need at least 8 if not 12 per channel&lt;/li&gt;
&lt;li&gt;I need a set of buttons that will control &lt;code&gt;solo&lt;/code&gt;, &lt;code&gt;mute&lt;/code&gt; and &lt;code&gt;record&lt;/code&gt; per channel. I don&#39;t feel like pressing a key combination to achieve any of those&lt;/li&gt;
&lt;li&gt;I need a section that will have a master volume control as well as a set of knobs to control the output parameters. At least 8-10 for that purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
That brings me to a whopping 13 potentiometers per channel plus 3-5 push buttons and 11 for the master control plus some 10+ push buttons. No microcontroller can handle that amount of analog inputs alone. This is why I came up with the idea of modular design that will help me accomplish my goal (some time in the unforeseeable future :D).
&lt;/p&gt;

&lt;h3&gt;The grand design&lt;/h3&gt;

&lt;p&gt;
I don&#39;t want to be limited by the number of inputs at any stage. That&#39;d be ridiculous. So instead of making an all-in-one design I am going for a modular, expand-as-you-go design that will allow me to basically define two types of modules:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A channel module that will pretty much be a device on its own, handling all the analog and digital inputs and being an I2C slave that will allow a master to read the state of all the knobs at once&lt;/li&gt;
&lt;li&gt;A master module capable of recognizing all the connected slaves and sending their values over MIDI as they change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each module will run its own ATMega382p (Arduino) with the necessary I2C hardware (like additional ADCs over I2C or I/O expanders if I choose to go with encoders rather than potentiometers). That way every module will be a slave and the master can ready the values of each control at a time of its choosing leaving the combining and transposition to MIDI commands to the master controller. Cool, ain&#39;t it?
&lt;/p&gt;

&lt;h3&gt;Let the fun begin&lt;/h3&gt;
&lt;p&gt;
So here I am, 3:40am, with that crazy idea in mind, putting it all on the blog. I really would like to make a big console for 32 channels but I think I&#39;ll start with 1 or 2 channels and the master to validate if the design scales.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Have fun! I know I will!&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;

 </content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/1598942123744476409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/1598942123744476409' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1598942123744476409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1598942123744476409'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/03/building-midi-console-with-arduino.html' title='Building a MIDI console with Arduino '/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-2629145591819145650</id><published>2020-03-23T14:08:00.000+01:00</published><updated>2020-03-23T14:08:05.690+01:00</updated><title type='text'>Vue.js and dialogs</title><content type='html'>&lt;p&gt;
Let&#39;s think for a moment about modal dialogs. What is their usage pattern? What are they for, I mean conceptually...
&lt;/p&gt;

&lt;h3&gt;Dialog unveiled&lt;/h3&gt;
&lt;p&gt;
When we create a dialog it is usually to gather some feedback from the user. It might be either a simple &lt;code&gt;Yes&lt;/code&gt; / &lt;code&gt;No&lt;/code&gt; or some form that the user needs to fill in and return that input after some form of interaction with that dialog.
&lt;/p&gt;
&lt;p&gt;
Unfortunately there is no direct support for this kinds of interactions in Vue.js (nor in any other reactive framework, to be honest). This means that we need to resort to stuff like this:
&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;&lt;code&gt;data() {
  return {
    isConfirmationDialogVisible: false
  }
},
methods: {
  showConfirmationDialog() {
    this.isConfirmationDialogVisible = true
  },
  hideConfirmationDialog() {
    this.isConfirmationDialogVisible = false
  },
  handleConfirm() {
    this.hideConfirmationDialog()
    // the dialog ended with &quot;OK&quot; - perform some action
  },
  handleCancel() {
    this.hideConfirmationDialog()
    // the dialog ended with &quot;Cancel&quot; - do nothing
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;
The reason why we&#39;re doing all the state mutation nonsense in every place where we want to use a dialog is that the general approach in framework such as Vue.js is to base everything on state and we&#39;re completely ignoring the imperative nature of some of the processes. What is even more disturbing is that quite frankly the &lt;code&gt;isConfirmationDialogVisible&lt;/code&gt; doesn&#39;t really belong with the place of use of the dialog. It should be an internal implementation detail of the dialog itself. But since we don&#39;t have implicit support for imperative programming with Vue.js it is sort of necessary to resort to stuff like that. But is it?
&lt;/p&gt;

&lt;h3&gt;API is not just props and events&lt;/h3&gt;
&lt;p&gt;
You might be tempted to think about the API of a component in terms of props that component accepts and events it emits. And even though they form a very important way of communication between parent and childs it is only 2/3rd of the story. Each method you define in the &lt;code&gt;methods&lt;/code&gt; block is essentially part of the API of a component.
&lt;/p&gt;

&lt;p&gt;
Suppose we have a dialog component that has the following two methods:
&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;&lt;code&gt;methods: {
  open() { ... },
  close() { ... }
}&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;
Now if we use that dialog component somewhere it is quite easy to call those methods:
&lt;/p&gt;

&lt;p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;MyDialog ref=&quot;dialog&quot; /&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  mounted() {
    this.$refs.dialog.open()
  },
  beforeDestroy() {
    this.$refs.dialog.close()
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;
This means that we can imperatively steer when the dialog is open and when it closes. This way the state of visibility of that dialog is stored with that dialog and not in every place that uses that dialog which improves the usability quite a bit.
&lt;/p&gt;

&lt;h3&gt;Promises, promises&lt;/h3&gt;

&lt;p&gt;
Knowing that we can actually call methods on components let&#39;s move on to the concepts of modal dialogs.
&lt;/p&gt;
&lt;p&gt;
Modal dialogs are dialogs that limit the possibility of user interaction to their content and usually finish with some result of that interaction. A good example is a popup that asks a question to which a user can say &lt;code&gt;Yes&lt;/code&gt; or &lt;code&gt;No&lt;/code&gt; or prompts the user to enter some data in which case there are usually two outcomes too: either the user entered the required information and approved his/her choice by pressing &lt;code&gt;OK&lt;/code&gt; or resigns from proceeding, usually with the user of a &lt;code&gt;Cancel&lt;/code&gt; button. It all bears a lot of resemblance to the &lt;code&gt;alert()&lt;/code&gt; and &lt;code&gt;confirm()&lt;/code&gt;, doesn&#39;t it?
&lt;/p&gt;
&lt;p&gt;
The way it is usually handled in other frameworks (the Windows API, GTK just to name a few) is that the call to the framework method is blocking and once the user interaction is done it returns some result. In the browser a blocking code like that would result in everything going sideways. However, and this is where JavaScript really shines, there is a built-in concept of values that will be delivered later in time. This is the concept of Promises.
&lt;/p&gt;

&lt;p&gt;
What if our dialog would expose a function like that:
&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;&lt;code&gt;methods: {
  async show() {
    return new Promise(resolve =&gt; {
      this.resolve = resolve
      this.show = true
    })
  },
  onOkButtonClick() {
    this.show = false
    this.resolve &amp;&amp; this.resolve(&#39;ok&#39;)
  },
  onCancelButtonClick() {
    this.show = false
    this.resolve &amp;&amp; this.resolve(&#39;cancel&#39;)
  },
},
data() {
  return {
    show: false,
    resolve: null
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;
Now that we have this we can use it in the code of a component that needs this kinds of interaction in a very nice way:
&lt;/p&gt;

&lt;p&gt;&lt;pre&gt;&lt;code&gt;methods: {
  save() {
    const confirmation = await this.$refs.dialog.show()
    if (confirmation === &#39;ok&#39;) {
      // do something, the user is OK with it :)
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;
The most important part of that approach is that you&#39;re not multiplying state that doesn&#39;t need to be multiplied and as a bonus your code expresses the intent: show a modal and react to the result of its interaction with the user
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Have fun!&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;

</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/2629145591819145650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/2629145591819145650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2629145591819145650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2629145591819145650'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/03/vuejs-and-dialogs.html' title='Vue.js and dialogs'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-6131759601627923091</id><published>2020-03-18T10:29:00.000+01:00</published><updated>2020-03-18T10:36:57.258+01:00</updated><title type='text'>How to be successful when coding from home?</title><content type='html'>&lt;p&gt;These are extraordinary circumstances for many organizations. The corona virus has forced a lot of people to stay home. This means that many people have found themselves in a situation they have never been before and might not feel very comfortable just being alone. In this post I&#39;ll try to share my tips for working remotely that I have gathered for over 7 years and being quite successful in it. Quite frankly I would never go back to the way things were before...&lt;/p&gt;

&lt;h3&gt;The bottom line&lt;/h3&gt;

&lt;p&gt;If you&#39;re like me and you don&#39;t feel like reading long posts here are the highlights:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Control is good - trust is better and pays off in spades! It is especially difficult for managers when they have no oversight over their workers but it is absolutely necessary to hold your horses and let the situation settle. This is where many managers will fail and only the best ones will prevail. That being said it is equally hard on employees to trust themselves.&lt;/li&gt;
  &lt;li&gt;If you&#39;re an employer you must believe in your people. They will do a good job even if it will take them time to adjust and get comfortable in the new situation. Judge the effects of work - not the workers - and remember that chemistry doesn&#39;t happen over night. Manage your expectations!&lt;/li&gt;
  &lt;li&gt;If you&#39;re an employee know that working from home doesn&#39;t mean you&#39;re off work. It just means that you have a really small office. It needs to be properly equipped and comfortable. Keep up the good work and you will prevail&lt;/li&gt;
  &lt;li&gt;Communication is key! Learn to use the tools at your disposal. Things like Skype, Hangouts, Zoom, Slack, Teams and Discord are there for you to take full advantage of what they provide. Make sure you have more than one tool at your disposal.&lt;/li&gt;
  &lt;li&gt;Limit the necessary communication. It is the key to not getting distracted. There is no such thing as &lt;i&gt;an urgent email.&lt;/i&gt; And it also means you need to have a discussion about it with your wife and kids. Be fair to your family!&lt;/li&gt;
  &lt;li&gt;If you like working in pair use it to keep connected with your peers. Tools like VS Code combined with a voice call help you do that!&lt;/li&gt;
  &lt;li&gt;Make sure you have more than one option to connect to the Internet. LANs do break and having a backup LTE connection will let you concentrate on work and it will put yours and your manager&#39;s mind at ease :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And one last thing...&lt;/p&gt;

&lt;p&gt;The thing I found most difficult is to accept yourself. There&#39;s nothing in the whole wide world that&#39;s worse than judging yourself over and over again to the point where you are so down you can&#39;t take anymore. There are times when we&#39;re overly productive and times when we suck, big time. No matter how you want to slice it the sine wave is the most perfect shape in the world. It&#39;s the rule all living things live by, no matter if they like it or not. Accepting it will help you understand where you are, where you are coming from and where you&#39;re headed.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Have fun!!!&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;

&lt;div style=&quot;display: none&quot;&gt;
&lt;p&gt;If you made it here and want to learn more about my experience with working from home - read on :)&lt;/p&gt;

&lt;h3&gt;The circumstances&lt;/h3&gt;

&lt;p&gt;My adventure with working from home begun some 14 years ago when I joined Sabre inc. It was the first company that employed proper VPN technology and gave us all laptops to work on. Since many teams were dispersed throughout different continents it was obvious that from time to time you would work in crazy hours. For example we have had regular team meetings every Thursday at 8pm CET. Staying at work for so long, although possible, was in fact not very practical (not to mention my wife was not very happy about it).&lt;/p&gt;

&lt;p&gt;On top of that there were times when I needed to work directly with a guy that lived on Hawaii. That&#39;s 12h difference from CET! To put it in perspective if some of you end your day at 5pm it was 5am (yes! the middle of the night!) for Walker. Walker was a very important person (a VIP you might say) because he was the original author of the software we were working on. So he has had all the intimate knowledge of the system and was the best person to learn from. Frankly I wouldn&#39;t like to be in his shoes getting up 4am just to have a call with some guys across the globe :) And did I mention I am not really a morning person?...&lt;/p&gt;

&lt;h3&gt;The solution&lt;/h3&gt;

&lt;p&gt;And so I came to the conclusion that it would make sense for me to start working in a timezone that&#39;s a bit of both: 2pm to 10pm. This would mean I would have plenty of overlap with Walker and the rest of the team based in the US yet enough time to take care of my daily business. The downside, though, was that there was nobody in the office after like 6pm and staying alone in a huge office wasn&#39;t my idea of fun. So I worked remotely for half a year. There were no papers to be signed, no permissions to be given - just my personal decision to have more time with the guys overseas.&lt;/p&gt;

&lt;p&gt;The first few days it felt really strange. I was organizing my home office for a few hours, reorganizing my desk every now and then to fit the new situation, then doing a bit of project work, having lots of time with the rest of the team in the States and in the evening watching a movie with my wife after work. The adjustment period went on for about a week and after that it felt like I was doing it forever.&lt;/p&gt;

&lt;p&gt;Now that I think about it in fact I &lt;strong&gt;was&lt;/strong&gt; doing it forever - just didn&#39;t realize it! I am a self learner. I didn&#39;t finish my study at the university, I wasn&#39;t particularly good in high school and even in ground school things were not looking very up for me. All because I preferred spending time coding. Yes, I started coding at the age of 12 and I knew I wanted to be a programmer when I was 6 years old :)... Quite frankly I don&#39;t know how I managed to meet that wonderful girl that I spent over 23 years with :) I think I just got lucky!&lt;/p&gt;

&lt;h3&gt;Communication&lt;/h3&gt;

&lt;p&gt;I am an introvert. My wife would say that&#39;s not really true but I know how I feel inside. It isn&#39;t a bad thing - it just means I can concentrate better when there&#39;s less people around me. Sure there are times when I am fed up with just my 4 walls and I am looking for some company. But that grows old very soon for me. Even though I can literally see the office from home with a naked eye I go there maybe once a month, often times even less. I found that it is way more productive if I can shut out everybody and just do coding. That led me to employing rules like checking emails only in the morning, keeping to the necessary minimum my interactions on Skype - you know what I mean.&lt;/p&gt;

&lt;p&gt;

&lt;h3&gt;How does that help you?&lt;/h3&gt;

&lt;/div&gt;


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/6131759601627923091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/6131759601627923091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/6131759601627923091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/6131759601627923091'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/03/how-to-be-successful-when-coding-from.html' title='How to be successful when coding from home?'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-1587355248136052931</id><published>2020-03-17T12:55:00.000+01:00</published><updated>2020-03-17T12:55:11.767+01:00</updated><title type='text'>Using multiple ssh keys with Github (or any other host)</title><content type='html'>&lt;p&gt;Imagine you&#39;re working on one machine with multiple clients. In that case each client might require you to have a separate account on Github. This means that you need to have separate SSH keys for those accounts too and that in turn means is a pain in the butt to have it working.&lt;/p&gt;
&lt;p&gt;If you&#39;re on Linux (and probably MacOS too) there&#39;s hope for you! Follow those simple steps to get everything setup so that you won&#39;t even notice it is there!&lt;/p&gt;

&lt;h3&gt;Step 1: Add a host entry in &lt;code&gt;~/.ssh/config&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Host client-github.com
     Hostname github.com
     User git
     IdentitiesOnly yes
     IdentityFile ~/.ssh/client_rsa
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows you to connect to a host named &lt;code&gt;client-github.com&lt;/code&gt; which will in fact connect to &lt;code&gt;github.com&lt;/code&gt; but with a specific identity file (ssh key)&lt;/p&gt;

&lt;h3&gt;Step 2: Add the following 2 entries to your &lt;code&gt;~/.gitconfig&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;[url &quot;ssh://git@client-github.com/client&quot;]
        insteadOf = ssh://git@github.com/client

[url &quot;ssh://git@client-github.com/client&quot;]
        insteadOf = git@github.com:client
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using &lt;code&gt;client-github.com&lt;/code&gt; is not really practical. There are instances (like linked npm modules from github.com) where you&#39;re not directly in control of the hostname. That&#39;s where the URL substitution in Git comes in handy. Whenever someone requests a URL from the client&#39;s namespace we substitute it with our custom address and everything&#39;s golden&lt;/p&gt;

&lt;p&gt;Obviously if you substitute the &lt;code&gt;client&lt;/code&gt; part of the custom hostname with the name of the client it will be easier for you to manage multiple such cases :) Just sayin&#39;...&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Have fun!&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/1587355248136052931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/1587355248136052931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1587355248136052931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1587355248136052931'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2020/03/using-multiple-ssh-keys-with-github-or.html' title='Using multiple ssh keys with Github (or any other host)'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-1488411477634567953</id><published>2019-09-27T17:53:00.001+02:00</published><updated>2019-09-27T17:53:56.341+02:00</updated><title type='text'>How to pass an interview?</title><content type='html'>This is sort of a generic post that I feel might help one or two people when they go for an interview. If you find it helpful throw me a comment. If you find it stupid and you feel that I am not right - say so as well. Criticism is WELCOMED!!!&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
The stage&lt;/h4&gt;
The stage is simple: you are looking for a new job. For the sake of simplicity I will focus on a new job for a programmer.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
The process&lt;/h4&gt;
It does matter if you&#39;re applying for a job that is way above your current experience or if you&#39;re applying as an expert in a field&amp;nbsp; your client requires. In the first case it is extremely easy to pass: all you need to do is be open, make sure you outline what you don&#39;t know and what you&#39;re keen on learning, what you expect to gain (besides money!) from your new position and chances are if the employer is smart enough (and you engaged enough) that things will play out just fine.&lt;br /&gt;
&lt;br /&gt;
The other situation is a bit different. You have to know what you&#39;re selling if you wish to sell it to someone. A good example (and a very good exercise before going to an interview) is to present your topic to an audience on a conference. So let&#39;s assume you apply for a position as an architect of some sort. Before you do the actual interview apply for a presentation at your local interest group (a meetup, conference - whatever!) and do the presentation. What&#39;s nice about it is you&#39;ll get immediate feedback from the audience. And remember: no feedback is also some feedback! It just means you have not been good enough to spark interest in your audience. And I don&#39;t mean Q and A session right after your presentation. If there are people hunting you after you&#39;re packed and ready to leave asking questions - you did a good job!&lt;br /&gt;
&lt;br /&gt;
The reason I am bringing public presentations up here is because those are equally stressful as an interview and touch on the same kind of topics that you will encounter during an interview. Pretty much the same stuff. Imagine, if you will, you&#39;re presenting in front of 100 people (not uncommon even on local meetups). And all of the sudden someone asks you a question you know absolutely nothing about. How would you react? How would you react in a similar situation during an interview?&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Epilogue...&lt;/h4&gt;
This far I have I have had countless interviews - only two of them were negative and I didn&#39;t even want the position I was applying for. From that I am gathering that you only pass interviews for positions you will actually find yourself useful. If you really really really want to work for Google - get interested in the stuff they do. If you want to work for Microsoft (although I find it hard to believe) get interested in what they do. Learn their ways and technology, learn about their requirements and prepare yourself for what will be asked. Don&#39;t be ashamed to say &lt;i&gt;I don&#39;t know&lt;/i&gt;. It is way worse to lie you know stuff than to admit it.</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/1488411477634567953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/1488411477634567953' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1488411477634567953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/1488411477634567953'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2019/09/how-to-pass-interview.html' title='How to pass an interview?'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-4627992202637615133</id><published>2019-03-06T02:28:00.000+01:00</published><updated>2019-03-06T02:28:51.770+01:00</updated><title type='text'>Designing as small stable Core XY 3D printer</title><content type='html'>&lt;h2&gt;The journey so far&lt;/h2&gt;

&lt;p&gt;I have been completely swallowed by the idea of designing my own 3D printer. Just like that. From the day I have put together my Ender 3 that finally came in from Ali Express all I could think of was this project of creating the smallest working CoreXY 3D printer possible. I don&#39;t actually care about the possible print size (unless it is smaller that 1cm per 1cm per 1cm). What I do care about is making the 3D printer easy to put together and solid as fuck.&lt;/p&gt;

&lt;p&gt;Currently I am at a point where the structure is in place (and it is a tweaked one I tell you), all the roles are also in place and what I fight for at this point is to make the mount for the roles stable enough to handle the Core XY load with 3D printed elements)&lt;/p&gt;

&lt;p&gt;Stay tuned for more information on how this printer is being created :D&lt;p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/4627992202637615133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/4627992202637615133' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/4627992202637615133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/4627992202637615133'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2019/03/designing-as-small-stable-core-xy-3d.html' title='Designing as small stable Core XY 3D printer'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-5395478005479684311</id><published>2018-11-25T17:59:00.000+01:00</published><updated>2018-11-25T17:59:31.963+01:00</updated><title type='text'>Making an UV image setter for PCBs</title><content type='html'>&lt;p&gt;This is going to be a quick one. I wanted to do one of these for a long time but somehow it eluded me for quite some time (too long if you ask me)&lt;/p&gt;

&lt;h2&gt;The problem&lt;/h2&gt;

&lt;p&gt;I need to make a PCB for a small circuit at home. Conveniently. After I&#39;m done designing the circuit it usually is late and the sun doesn&#39;t shine no more. I want to be able to use the photoresist dry film (foil) and I want it to be fast!&lt;p&gt;

&lt;h2&gt;The solution&lt;/h2&gt;

&lt;p&gt;I used to use a 500W halogen, then an energy-saving fluorescent lamp but all of those things were just cumbersome. Finally I have decided to make use of UV emitting diodes.&lt;/p&gt;

&lt;p&gt;See the following picture of a ready-made product:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlrtQngkXgEFQsADz4dzhyphenhyphenf9nNfMJEHkbS9N_LIvL1NkMAYRO1VlUHDBbL2YiF6Gg8VDYqJxfvQuLM9ZEcGuxLNXDyVYgVH5pDE_7M4wJSQ3v4DGNHgCHRkrsR1vtTtxudvS48c3bcYzQe/s1600/IMG_1682.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlrtQngkXgEFQsADz4dzhyphenhyphenf9nNfMJEHkbS9N_LIvL1NkMAYRO1VlUHDBbL2YiF6Gg8VDYqJxfvQuLM9ZEcGuxLNXDyVYgVH5pDE_7M4wJSQ3v4DGNHgCHRkrsR1vtTtxudvS48c3bcYzQe/s320/IMG_1682.JPG&quot; width=&quot;240&quot; height=&quot;320&quot; data-original-width=&quot;480&quot; data-original-height=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;The device is powered by a 3 cell LiPo battery (I have a bunch of them for my flying toys). The time it takes to properly develop the foil is ABSOLUTELY SHORTEST FROM ALL THE LIGHT SOURCES I USED BEFORE!!!&lt;/p&gt;

&lt;p&gt;The 500W halogen needed circa 30 minutes in the setup I used. The energy-saving light bulb needed 12.5 minutes. This little toy does the same and more in 90 seconds!!!&lt;/p&gt;


&lt;h2&gt;The making&lt;/h2&gt;

&lt;p&gt;Making such a toy is extremely simple. You just cut as many pieces to length as much space you have in the housing of your choosing (I used the Z23 housing where I have cut a full-size hole in one of the parts).&lt;/p&gt;

&lt;p&gt;Next you cut a piece of paper that fits inside the housing. Once you do that take the pieces of strips and glue them on to the piece of paper in a similar way that you see on the picture above. The point here is to make the as evenly spaced as possible.&lt;/p&gt;

&lt;p&gt;Then you solder them to form a strip (plus with plus, minus with minus). On one end you solder any kind of connector (I went for the small JST one because I have a lot of them). Then just make a hole on the side where the leads with the connector are coming out.&lt;/p&gt;

&lt;p&gt;Finally place that paper with glued strips inside, apply power and enjoy!&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Happy PCBing!&lt;/i&gt;&lt;/p&gt;


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/5395478005479684311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/5395478005479684311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5395478005479684311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5395478005479684311'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/11/making-uv-image-setter-for-pcbs.html' title='Making an UV image setter for PCBs'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlrtQngkXgEFQsADz4dzhyphenhyphenf9nNfMJEHkbS9N_LIvL1NkMAYRO1VlUHDBbL2YiF6Gg8VDYqJxfvQuLM9ZEcGuxLNXDyVYgVH5pDE_7M4wJSQ3v4DGNHgCHRkrsR1vtTtxudvS48c3bcYzQe/s72-c/IMG_1682.JPG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-2629366908689339835</id><published>2018-11-23T11:32:00.000+01:00</published><updated>2018-11-23T11:32:38.787+01:00</updated><title type='text'>The Flame Wars - story of my life</title><content type='html'>&lt;p&gt;
Flame wars have been with us for God knows how long. Christianity vs all other religions, Islam vs everyone else, socialism vs capitalism, Atari vs Commodore, Amiga vs PC, Macintosh vs the World, Linux vs everyone else. Fighting for our believes seems to be at the core of our nature. We just can’t help thinking that what we think is best must be the best - because we deemed it to be the case.
&lt;/p&gt;
&lt;p&gt;
Developers are a particular strain of oddities: Whatever technology we seem to work with at the time seems to be either the evil incarnated or the impersonation of God - depending on the current hype among our friends that we trust know better. Very seldom it is the case we grow big enough balls to actually go over the fence, dig into the dirt and figure out for ourselves if the grass on the other end is really so gray as we deem it to be.
&lt;/p&gt;
&lt;p&gt;
It has been an eye opening experience every time I took a turn in my career when it came to the tools I worked with. 
&lt;/p&gt;
&lt;p&gt;
I started in the 7th heaven owning an Atari 800XE and 3 games I could barely hold still while loading a game from a tape storage. For that reason I started to learn what the keyboard and TV set has to offer beyond playing Mr Robot and Forth Apocalypse and I discovered that, in point of fact, Basic was a part of the package.
&lt;/p&gt;
&lt;p&gt;
Soon after that I became a sworn 6502/C64 freak at the age of 14. I know. I betrayed. I was the outcast. But I was doing ora-dycpys going over side borders while playing ripped tunes and waving Dedal logos. And I did it all in machine language - not even assembly! All I have had was the Final Replay 2 cartridge but for reasons I cannot fathom it was the best thing that ever happened for me. I was able to see the results of my work upon issuing a single sys command. And it looked great!
&lt;/p&gt;
&lt;p&gt;
At that time Amiga was “the better game machine for me”. I mean, with all due respect, I still think that the playability of Giana Sisters, the Mario clone for Commodore computers, was way better on C64 than it was on any platform (even XBox!). Having said that I was kind of socially pressed into wanting the A500 with 512Kb of Slow RAM extension to be able to play Pinball Dreams and IK4+. But playing games was never my thing. After I saw how much Giana Sisters sucked by comparison I started looking for things to do with my shiny new computer. Pascal was there, but the animation example I saw was visually so bad that I couldn’t stand watching it. The C example didn’t even compile so I thought it was a waste of time to get interested in it. But the good old low level language, Motorola 68k assembler, was quite a nice fit for me after having a few years of experience in programming registers on its older uncle. Man, those plasma screens I loved so much! I was staring at it for hours! I was finally home!!!
&lt;/p&gt;
&lt;p&gt;
At that time I remember reading a quite far reaching article about code quality. A couple of demo scene Gods discussed if it makes sense to write good quality code or if it is more important to just code it in the fastest way possible, win the compo at a demo party and move on to the next one. A question I sure hope the industry has answered so far to everyone’s satisfaction.
&lt;/p&gt;
&lt;p&gt;
Being bored writing sinus scrolls, 3D animations and plasmas I started looking into this promised land Amos was said to be. With its Amal animation language targeting Amiga’s coprocessors it was told to be even better than asm itself. I remember it being the first IDE having an integrated debugger, forward function declaration and (upon pressing F9) code folding. Man! I missed that for years afterwards!
&lt;/p&gt;
&lt;p&gt;
Then one day everything changed. My beloved A1200 was (again, upon the pressure of friends) exchanged to a 486SX with 50MB hard-drive. It was running DOS, Norton Commander, it looked bad (compared to A1200’s workbench) and what I had no idea then it was the first computer running an OS that was not Unix-like. Apparently, for what seems to be forever, I have fallen into the Redmond dream that I was unable to wake up from.
&lt;/p&gt;
&lt;p&gt;
I remember a few years after that trying to install RedHat Linux from a 23 floppy disks installation - and failing miserably. I thought that those “Linux” guys must be insane to be using something like that. I was a sworn DOS enthusiast! I discovered Windows 3.1 and the only thing it was good for was multitasking to run the BBS software and at the same time to be able to code in Turbo Pascal that I fell in love with in the meantime. Pascal wasn’t fast enough though to write intros/demos so me and my friend resorted to “db 66” asm instructions to speed up double buffering.
&lt;/p&gt;
&lt;p&gt;
Not long after that I learned that programming isn’t really something lots of people do particularly well - me included. That was when I discovered The Almighty Internet. Suddenly the knowledge that I craved for so much for so long became within my reach. But it was so overwhelming!!! Just going through some examples that I found on swagger took me a lot of time. Those were the times when I first saw Qnix - a windowing system-enabled one floppy-disk, Unix-like, free to use real time operating system. So Unix did have some appeal after all, I thought. I went even deeper when I learned about the Linux Router Project - a one-floppy-disk Linux distribution that did IP routing and masquerading out of the box. I knew Linux was the one - but it was so different than Windows and Dos Navigator that I grew so accustomed to!! All the things were different. That was just a hassle I was not ready to go through.
&lt;/p&gt;
&lt;p&gt;
Fast forward a few years and the Turbo Pascal I worked in became Delphi and my professional career was booming! I was moving to a different country, founding my second business - I was on the roll! To have everything in check instead of buying Windows XP I decided to try out this “SUSE Liunux” as it was promised to “just install and work” on my PC. Well, it did. But it was soooo different than Windows XP and… Delphi didn’t run there. I was still deep in the Redmond dream.
&lt;/p&gt;
&lt;p&gt;
I don’t remember when it really happened but it must have been when I received the Ubuntu 7 something CD for free. It really delivered on the promise to be approachable enough for everyone - this time me included. But Delphi still didn’t run there. By accident that was the time I went to a seminar in Warsaw where the successor of Delphi 7 was announced and I realized that this is the end of what I was able to get out of the platform. So I started looking…
&lt;/p&gt;
&lt;p&gt;
At that time I worked in a corporation that offered me an option to learn Java and .NET. C# looked like a natural choice (being coordinated by the creator of Delphi himself) but for reasons I cannot fathom till this day I decided to go with Java. The first years were a disaster! Nothing was like it should have been. Java developers spoke of things I had no idea even had names (like refactoring, unit testing, clean code, design patterns) although upon deeper investigation it looked like we spoke about those same things - just naming them differently.
&lt;/p&gt;
&lt;p&gt;
I fell in love with Groovy and Maven (I know - I’m different that way). I use both of those tools till this day with great proficiency. I think that Maven was the best thing that ever happened to Java. It made it approachable for mere mortals and freed us from Ant hell. Groovy on the other hand was for me the Pascal equivalent on the JVM. It had the concept of properties that I missed so much ever since I left Delphi behind. But at the same time I unwillingly became independent of the environment I worked in. Linux, Windows, OSX - I didn’t care anymore. So I realized one of my long-lived dreams and switched fully to Ubuntu - the Linux platform for the rest of us :) It was a natural step because all production servers were running Linux so using SSH that was not (and still isn’t) present on Windows felt so natural. And so, Windows became “the OS I sometimes run”. I do remember the day when I installed Linux exclusively without dual-boot. It felt weird - but good.
&lt;/p&gt;
&lt;p&gt;
Since then I moved from Java to frontend development. Something I thought I had some idea of but was proven sooooooo wrong. Learned that what you see is not really what you will get (as in I finally learned what the hell everyone else was talking about in relation to Internet Explorer 6). But I love every bit of it. It gives out of the box tooling that on other platforms you need to pay good money for. To some extent I am even happy I learned about frontend development through the Ember.js perspective. It was the worst thing after getting struck by Java Server Faces but it made me explore the domain to see if there’s something that can substitute this horrible piece of machinery. So I learned about React and fell in love with it, I also learned about Angular and how it makes development more like I was used to from my times in Java and ended falling completely in love with Vue.js.
&lt;/p&gt;
&lt;p&gt;
Then I decided to move to a company that thinks very little of frontend development but is really big on Sitecore. If you don’t know what Sitecore is think Wordpress on .NET that you can pay for because you think it is better than X or Y. This meant for me taking a round trip to the .NET world and the C# language.
&lt;/p&gt;
&lt;p&gt;
At each step after a few months of digging in I felt my passion for software development giving away field to understanding of capabilities. Every week/month/year I meet sworn enemies of technology X than can give me 5, 10 sometimes even 20 reasons for not using the other, legacy, frameworks, languages, platforms. The truth however is that everything has its reason for existence. Yes, even jQuery and goto. I just wish I learned that years ago. The only thing that really counts is writing code for other developers to read (regardless of the platform/language) and questioning the status quo if it makes your life harder.
&lt;/p&gt;
&lt;p&gt;
So going from 6502, through M68k, Amos/Amal, Pascal, Delphi, Java, JS and the browser and now .NET and Sitecore I learned only one thing: developing software is easy. But doing it right is hard. And if you don’t use whatever means necessary to help you out then sinking in the pool of your own blood and excrements is as obvious as the fact that sun’s rising in the east. The rule for me now is to first learn for myself if a piece of tech is useful in a context - not “in general”. And as a rule it has its exception for me: JSF. Everything else I learned over the years made me a better programmer, person, husband and father. 
&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Happy years!&lt;/i&gt;&lt;/p&gt;


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/2629366908689339835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/2629366908689339835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2629366908689339835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2629366908689339835'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/11/the-flame-wars-story-of-my-life.html' title='The Flame Wars - story of my life'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-6870521476252289652</id><published>2018-10-31T11:36:00.000+01:00</published><updated>2018-10-31T11:36:11.504+01:00</updated><title type='text'>Creating PCBs</title><content type='html'>&lt;p&gt;I have been working lately on perfecting a formula for preparing PCBs. If you&#39;re like me and like your designs tried out faster than a few days read on.&lt;/p&gt;

&lt;h2&gt;Assumptions&lt;/h2&gt;

&lt;p&gt;I am assuming you either are using the applications and materials that I used or you are happy to realize the same functions in the application you are using. I will be using Linux, KiCAD, a PDF viewer for printing and chemicals available in Poland, where I live.&lt;p&gt;

&lt;h2&gt;Preparing the printout&lt;/h2&gt;

&lt;p&gt;The following assumes you can use KiCAD. KiCAD&#39;s printing functionality is basically broken. The quality of printouts is so low you can&#39;t do anything with it. The following mitigates that by using Plot.&lt;/p&gt;

&lt;p&gt;When creating designs that contain through-hole components make sure to check the size of pads. By default they are tiny-tiny small and can easily break when heat is applied. To change the parameters of a pad right-click on, select &lt;code&gt;Properties&lt;/code&gt; and set the &lt;code&gt;Hole shape&lt;/code&gt; to &lt;code&gt;Oval&lt;/code&gt;, &lt;code&gt;Size X&lt;/code&gt; and &lt;code&gt;Size Y&lt;/code&gt; to at least &lt;code&gt;2&lt;/code&gt;. With that there is probably enough space to solder.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create your design&lt;/li&gt;
  &lt;li&gt;Select &lt;code&gt;File&lt;/code&gt; / &lt;code&gt;Plot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Set &lt;code&gt;Plot format&lt;/code&gt; to &lt;code&gt;PDF&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Select the copper layers&lt;/li&gt;
  &lt;li&gt;Select &lt;code&gt;Mirrored plot&lt;/code&gt; and &lt;code&gt;Negative plot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Set &lt;code&gt;Drill marks&lt;/code&gt; to &lt;code&gt;Actual size&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Click &lt;code&gt;Plot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Open the created PDF and print it on a Canson calcque&lt;/li&gt;
  &lt;li&gt;Use &lt;i&gt;Density Toner&lt;/i&gt; to even the traces on the layout. &lt;i&gt;Density Toner&lt;/i&gt; is basically rectified gasoline which melts the toner making it evenly black in all spots. This prevents the printout to leak UV rays through&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Depending on your printer (I use OKI C332 laser printer) it is important to set the printout density to maximum. That black toner is all that will block the UV rays from the light-sensitive material!&lt;/p&gt;

&lt;h2&gt;Preparint the PCB&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Cut out a piece of laminat to the size of your project. You don&#39;t need any excess - that&#39;s a waste I don&#39;t like&lt;/li&gt;
  &lt;li&gt;Cut out the printed layout to the size of your PCB. Again, I do that precisely which then makes aligning things easy&lt;/li&gt;
  &lt;li&gt;Cut out a piece of light-sensitive foil with additional 5-10mm. That excess is needed for the board to be exactly covered form side to side&lt;/li&gt;
  &lt;li&gt;Clean the PCB. I mean like &lt;i&gt;really, really well&lt;/i&gt;. I use a special sanding block for cleaning PCBs that I bought ages ago but a very fine sanding paper will do just fine. Don&#39;t overdo it - you don&#39;t want the copper layer to get too thin!&lt;/li&gt;
  &lt;li&gt;Wipe the board with a clean tissue so that any dust is removed from the surface&lt;/li&gt;
  &lt;li&gt;Peal the cover off of the foil on the inner-side. I do that with a piece of tape - works every time with absolutely no hassle&lt;/li&gt;
  &lt;li&gt;Place the foil on the PCB - the side that had the outer foil removed&lt;/li&gt;
  &lt;li&gt;Make sure there are no air bubbles or dust bubbles between the foil and PCB&lt;/li&gt;
  &lt;li&gt;Put the PCB between a folded sheet of paper (PCB towards the fold!) to form a sandwitch&lt;/li&gt;
  &lt;li&gt;Run the sandwitch through laminator at least 3 times. Make sure the laminator is properly heated!&lt;/li&gt;
  &lt;li&gt;Remove paper from sandwitch leaving only PCB. Beware not to peal of the foil from PCB&lt;/li&gt;
  &lt;li&gt;Put the printed layout toner-down on the PCB&lt;/li&gt;
  &lt;li&gt;Spray the PCB with layout on it with Transparent and remove all air bubbles&lt;/li&gt;
  &lt;li&gt;Cover the PCB with a plexi and make sure there are no air bubbles. If there are then you either have to litle Transparent or the field is not even.&lt;/li&gt;
  &lt;li&gt;Place a 32W energy saving bulb 22cm from the PCB.&lt;/li&gt;
  &lt;li&gt;Turn on the light source for 12-13 minutes&lt;/li&gt;
  &lt;li&gt;Remove the PCB and put it in a dark place for 10 minutes (necessary for the chemical process to finish)&lt;/li&gt;
  &lt;li&gt;Remove the outer protective foil - watch out not to break the layout!&lt;/li&gt;
  &lt;li&gt;Use foil developer for 2 minutes. While developing use a soft brush to remove the disolved foil. Do NOT exceed 2 minutes!&lt;/li&gt;
  &lt;li&gt;Wash the PCB under warm running water and using hands &lt;u&gt;delicately&lt;/u&gt; remove any remaining pieces of foil.&lt;/li&gt;
  &lt;li&gt;Put the PCB under light for 5 minutes. That way if there are any parts of the foil lefy they will turn blue and you&#39;ll know you have to start again&lt;/li&gt;
  &lt;li&gt;Put the PCB in a dark place for 5 minutes for the chemical process of hardening the foil to settle&lt;/li&gt;
  &lt;li&gt;Use B327 to remove non-covered parts of the copper; Don&#39;t keep it too long.&lt;/li&gt;
  &lt;li&gt;Once all the parts are disolved put the PCB under running water and wash excessively&lt;/li&gt;
  &lt;li&gt;Pour acetone on the board using surface tension to flow the liquid from one side to another. Do that until the foil peels of from the traces&lt;/li&gt;
  &lt;li&gt;Wash under running water&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That&#39;s it! With luck the PCB can have extremely small traces (requires good printer which the C332 is not) and very delicate handling especially when washing out the unexposed foil. I stick to 0,25mm traces and above but even that can sometimes go wrong. 0,5mm traces are guaranteed to be 100% successful.&lt;/p&gt;

&lt;h3&gt;Important remarks&lt;/h3&gt;

&lt;p&gt;Don&#39;t rush things! With the exception of exposing the foil for too long and developing the foil for too long take your time! Rushing things is the worst you can do. This process requires you to be gentle with the board, precise and methodical. Rushing things will only get you to broken traces.&lt;p&gt;

&lt;p&gt;That is it! Happy etching!&lt;/p&gt;


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/6870521476252289652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/6870521476252289652' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/6870521476252289652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/6870521476252289652'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/10/creating-pcbs.html' title='Creating PCBs'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-2351889342508466172</id><published>2018-09-19T01:24:00.000+02:00</published><updated>2018-09-19T01:24:04.177+02:00</updated><title type='text'>POI 10, tests and coverage</title><content type='html'>&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;You&#39;re using POI 10 with &lt;code&gt;@poi/plugin-karma&lt;/code&gt; and want to get coverage of your unit tests. The way to do it is to specify:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  plugins: [
    require(&#39;@poi/plugin-karma&#39;)({
      coverage: true,
    })
  ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and theoretically you should be all set. Only that it won&#39;t work:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TypeError: Cannot read property &#39;preLoaders&#39; of undefined&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&#39;ve looked everywhere and it seems that it is, unfortunately, not a known problem. What is even worse the GitHub repo with POI sources, version 10, is GONE! I mean I understand everything but removing history of an opensource project - that is a bit too much for me. SHAME ON YOU, EGOIST!&lt;/p&gt;

&lt;h2&gt;The solution&lt;/h2&gt;

&lt;p&gt;The problem is that &lt;code&gt;@poi/plugin-karma&lt;/code&gt; taps directly to options of the &lt;code&gt;vue-loader&lt;/code&gt; whist seems to be undefined at that point. The quick and dirty solution is to add those options:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  plugins: [
    require(&#39;@poi/plugin-karma&#39;)({
      coverage: true,
      chainWebpack (config) {
        config.module.rule(&#39;vue&#39;).use(&#39;vue-loader&#39;).options({})
      }
    })
  ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I need to dig more into the matter why &lt;code&gt;vue-loader&lt;/code&gt; isn&#39;t configured there and why the hell when testing a Vue.js SFC still causes errors but for now for testing just javascript code the above solution works&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Happy coding&lt;/i&gt;&lt;/p&gt;

</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/2351889342508466172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/2351889342508466172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2351889342508466172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2351889342508466172'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/09/poi-10-tests-and-coverage.html' title='POI 10, tests and coverage'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-3810811407071694445</id><published>2018-09-14T13:03:00.001+02:00</published><updated>2018-09-14T13:03:36.501+02:00</updated><title type='text'>Replacing strings in proxied response using Apache mod_substitute</title><content type='html'>&lt;p&gt;This is another quicky but it took me forever to finally figure it out - maybe someone will have that same problem...&lt;/p&gt;

&lt;h2&gt;The problem&lt;/h2&gt;

&lt;p&gt;You&#39;re working on a site that uses Apache2 proxy to merge your local frontend development environment with a remote site providing the content. That is easy to setup:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ProxyRequests Off
ProxyPreserveHost Off

ProxyPass &quot;/path-to-a-resource&quot; &quot;http://localhost:3000/path-to-local-resource&quot;
ProxyPass / http://remote-host/
ProxyPassReverse / http://remote-host/&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all is nice and dandy until all you want to do is just to merge the remote site with local resources on localhost. It starts to get interesting when you want to modify the content sent by upstream server. Why? Well... let&#39;s say links in that sent HTML are absolute and you&#39;d like them to be relative. There&#39;s a ton of options that are available once you can do that!&lt;/p&gt;

&lt;h2&gt;The solution&lt;/h2&gt;

&lt;p&gt;To be able to substitute strings in the response sent by upstream server there are 3 things that need to happen:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Enable the &lt;code&gt;mod_substitute&lt;/code&gt; (&lt;code&gt;$ sudo a2enmod substitute&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Enable filtering using &lt;code&gt;mod_substitute&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Specify replacement rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second part is what gave me a headache Today. Basically you need to understand 2 things: when Apache does the substitution it needs to have the full page received to be able to perform the substitution. That doesn&#39;t happen automatically. And then once the substitution is done Apache needs to put it all back together and send it to the browser. It&#39;s all done using the following for HMTL files only:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;AddOutputFilterByType INFLATE;SUBSTITUTE;DEFLATE text/html&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And last but not least: we need some substitutions to see the effect. For the purpose of demonstration we&#39;ll replace all &lt;code&gt;class&lt;/code&gt; attributes with &lt;code&gt;TEST&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Substitute &quot;s|class|TEST|i&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&#39;s it! It&#39;s easy as pie when you know the deal :) I know I&#39;ll be using it more and more in the future!&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Happy coding!&lt;/i&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/3810811407071694445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/3810811407071694445' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3810811407071694445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3810811407071694445'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/09/replacing-strings-in-proxied-response.html' title='Replacing strings in proxied response using Apache mod_substitute'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-5776939830182722614</id><published>2018-07-06T19:31:00.000+02:00</published><updated>2018-07-06T19:31:55.839+02:00</updated><title type='text'>Handling new POI&#39;s publicPath</title><content type='html'>&lt;p&gt;Today I wasted over 3 hours frantically looking for explanation why the hell POI&#39;s &lt;code&gt;publicPath&lt;/code&gt; setting thinks I am an idiot and it knows better what I want. So this is a quick post to let you know what you should do if you &lt;strong&gt;really&lt;/strong&gt; want to change the &lt;code&gt;output.publicPath&lt;/code&gt; in a POI-managed project.&lt;/p&gt;

&lt;h3&gt;The problem&lt;/h3&gt;

&lt;p&gt;Imagine you&#39;re working on some project that has pre-existing sources and their location is (surprisingly) not in the root of your server. That&#39;s the case every single time when you&#39;re working on existing apps trying to induce some build system on them to bundle up the scripts and stylesheets.&lt;/p&gt;

&lt;p&gt;Usually, for those cases Webpack has a special configuration option &lt;code&gt;output.publicPath&lt;/code&gt; that handles everything for you and life&#39;s good. POI, on the other hand, has that option exposed at the top level - but with a twist: it only works in final build and not in development mode.&lt;/p&gt;

&lt;p&gt;The problem is, however, that if you&#39;d like to work against an existing server that produces HTML and other artifacts you need to comply with that structure regardless of the mode. Unfortunately, POI fucking knows better! And here&#39;s the relevant point in POI&#39;s code that does it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
function getPublicPath(command, publicPath) {
  if (command === &#39;build&#39; &amp;&amp; typeof publicPath === &#39;string&#39;) {
    return /\/$/.test(publicPath) || publicPath === &#39;&#39;
      ? publicPath
      : publicPath + &#39;/&#39;
  }
  return &#39;/&#39;
}

module.exports = getPublicPath
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I have no idea what was going through EGOIST&#39;s head at the time of writing but it must have been something really, really strong. Not good for opensource as it breaks the fundamental rule of least surrprise.&lt;/p&gt;

&lt;h3&gt;The fix&lt;/h3&gt;

&lt;p&gt;Instead of setting the &lt;code&gt;publicPath&lt;/code&gt; in &lt;code&gt;poi.config.js&lt;/code&gt; or setting it via command-line parameter override it in the resulting Webpack configuration like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module.exports = {
  configureWebpack(config, context) {
    // we&#39;re not setting publicPath as the general configuration option
    // because some sick bastard decided this will only have an effect
    // in production mode and we need it everywhere. Talk about predictability...
    config.output.publicPath = &#39;/path/where/everything/lives/&#39;
    return config
  },&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With that life&#39;s good again (even thought it was so damn frustrating Today)&lt;/p&gt;

&lt;h3&gt;The architecture&lt;/h3&gt;

&lt;p&gt;Working on projects where the content is delivered from some sort of CMS or other app that has a fat backend isn&#39;t easy. It usually boils down to having &lt;em&gt;everything&lt;/em&gt; running locally, even if we don&#39;t need it. There is, however, a better way of doing it! Use some reverse proxy to route traffic to your browser from 2 different sources: the backend and the frontend in development mode. Here&#39;s an example configuration with Apache2 but you can do much much more than that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;VirtualHost :80&amp;gt;
    ServerName my-app.local

    # Make sure no caching is induced so that refresh always brings the latest version
    # run &quot;sudo a2enmod headers&quot; to enable headers module
    Header set Cache-Control no-cache

    # run &quot;sudo a2enmod proxy_http&quot; to enable http proxy
    ProxyRequests     off
    ProxyPreserveHost off

    # Serve all theme files from local development server
    ProxyPassMatch    &quot;^\/path\/where\/everything\/lives\/(.*)$&quot; &quot;http://localhost:10001/path/where/everything/lives/$1&quot;

    # Required by Hot Reload (run &quot;sudo a2enmod proxy_wstunnel&quot; to enable ws proxy)
    ProxyPassMatch    &quot;^/(.+).hot-update.js$&quot; &quot;http://localhost:10001/$1.hot-update.js&quot;
    ProxyPassMatch    &quot;^/(.+).hot-update.json$&quot; &quot;http://localhost:10001/$1.hot-update.json&quot;
    ProxyPassMatch    &quot;^/sockjs-node/(.+)/websocket&quot; &quot;ws://localhost:10001/sockjs-node/$1/websocket&quot;
    ProxyPassMatch    &quot;^/sockjs-node/(.+)$&quot; &quot;http://localhost:10001/sockjs-node/$1&quot;

    # Serve everything else from remote server
    ProxyPass         / http://dev-machine.somedomain.com/
    ProxyPassReverse  / http://dev-machine.somedomain.com/

&amp;lt;/VirtualHost :80&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, don&#39;t forget to set &lt;code&gt;NameVitualHost *:80&lt;/code&gt; or the name-based virtual hosting just won&#39;t work. Now with that in place add the following entry to your &lt;code&gt;/etc/hosts&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;127.0.0.1   my-app.local&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and you&#39;re all set.&lt;/p&gt;

&lt;p&gt;You can of course fiddle with it, add SSL support if your backend server requires it, but the point here is that it is possible and you can work without installing heavy backend to work on frontend!&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Happy coding!&lt;/i&gt;&lt;/p&gt;

  </content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/5776939830182722614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/5776939830182722614' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5776939830182722614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5776939830182722614'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/07/handling-new-pois-publicpath.html' title='Handling new POI&#39;s publicPath'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-3448523765447900243</id><published>2018-06-23T13:57:00.000+02:00</published><updated>2018-06-23T14:06:02.223+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vscode"/><category scheme="http://www.blogger.com/atom/ns#" term="vue"/><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><category scheme="http://www.blogger.com/atom/ns#" term="vuejs"/><title type='text'>Scaffolding a new Vue.js component</title><content type='html'>&lt;p&gt;I&#39;ve been working for the past few months on a travel portal rewriting parts of it from old jQuery code to Vue.js - and learning a lot of stuff in the process. One thing that I learned the hard way is that scaffolding that&#39;s built in into Vetur is just not for me. It is too simple.&lt;/p&gt;

&lt;p&gt;The naming convention we have for our component files is for them to have the same name as the file they exist in. So basically &lt;code&gt;TestMe.vue&lt;/code&gt; becomes&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;test-me&quot;&amp;gt;
    ...content
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import Vue from &#39;vue&#39;
import Component from &#39;component&#39;

@Component({})
export default class TestMe extends Vue {
}
&amp;lt;/script&amp;gt;

&amp;lt;style lang=&quot;scss&quot; scoped&amp;gt;
.test-me {
}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Makes sense?&lt;/p&gt;

&lt;p&gt;The problem is that having to type this in every time I create a new component (and the number of those grows like creazy!) is tedious. So I finally got to it and created a snipped that works for me:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/padcom/34ef4594c2d33eb08272d921bc16c08c.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;That&#39;s it! You type &quot;&lt;code&gt;sfc&lt;/code&gt;&quot;, press [Tab] and the component is ready to be worked on by magic of the VS Code templating engine.&lt;/p&gt;

&lt;p&gt;The first thing that&#39;ll be edited is the name of the exported class. If it is OK then just press [Tab] to move to the name of the CSS class. Edit it if you must then press [Tab] again and you&#39;ll be able to select the processor for styles. The next thing that you get to customize is if the styles should be scoped. Once on it either press [Tab] to go with scoped styles or [Delete] and then [Tab] to go without scoped styles. Finally you arrive at the &lt;code&gt;Hello, world!&lt;/code&gt; text where the editing of your component begins.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Have a nice day!&lt;/i&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/3448523765447900243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/3448523765447900243' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3448523765447900243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/3448523765447900243'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/06/scaffolding-new-vuejs-component.html' title='Scaffolding a new Vue.js component'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-7026676294334866406</id><published>2018-06-16T17:11:00.000+02:00</published><updated>2018-06-23T14:07:12.254+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="component"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="vue"/><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><category scheme="http://www.blogger.com/atom/ns#" term="vuejs"/><title type='text'>Vue.js - editor components</title><content type='html'>&lt;p&gt;When talking about creating applications in Vue.js it is not hard to find one that does something to data. Obviously for state management there&#39;s Vuex, Redux and other stores but in this post we&#39;re going to focus strictly on passing state via props to components that one could generally call &lt;i&gt;controls&lt;/i&gt; - so more on the lines of custom inputs.&lt;/p&gt;

&lt;h2&gt;The 3 cases&lt;/h2&gt;

&lt;p&gt;There are 3 cases that we will encounter when passing data down to controls:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We&#39;re passing in primitive values (strings, numbers, booleans)&lt;/li&gt;
  &lt;li&gt;We&#39;re passing in complex reactive objects (think: list of people)&lt;/li&gt;
  &lt;li&gt;We&#39;re passing in a complex reactive object but we&#39;d like to treat it as a primitive and have atomic changes to all its fields&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Primitives&lt;/h3&gt;

&lt;p&gt;In the case of primitives the situation is dead simple: use &lt;code&gt;v-model&lt;/code&gt;, you can react to changes by hooking up to the &lt;code&gt;input&lt;/code&gt; event - done. The documentation is fantastic in that area so if you&#39;d like to know more about it dig in!&lt;/p&gt;

&lt;h3&gt;Reactive complex objects&lt;/h3&gt;

&lt;p&gt;Imagine you have a data structure like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;data = { firstName: &#39;John&#39;, lastName: &#39;Doe&#39; }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case if you create a control (we&#39;ll call it &lt;code&gt;DataEdit.vue&lt;/code&gt;) that you&#39;d like to immediately edit the fields you could do something like that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;input v-model=&quot;value.firstName&quot;&amp;gt;
    &amp;lt;input v-model=&quot;value.lastName&quot;&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  props: {
    value: Object
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means that if used in a parent component (&lt;code&gt;ContactForm.vue&lt;/code&gt;) like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;{{ person.firstName }} - {{ person.lastName }}&amp;lt;/h1&amp;gt;
    &amp;lt;DataEdit &lt;b&gt;:value=&quot;person&quot;&lt;/b&gt; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import DataEdit from &#39;./DataEdit.vue&#39;

export default {
  components: {
    DataEdit
  },
  data() {
    return {
      person: { firstName: &#39;John&#39;, lastName: &#39;Doe&#39; }
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then changes to values in inputs in &lt;code&gt;DataEdit.vue&lt;/code&gt; component will immediately be reflected in &lt;code&gt;ContactForm.vue&lt;/code&gt;. Vue&#39;s reactive system at its best.&lt;/p&gt;

&lt;h3&gt;Treating complex objects like a value&lt;/h3&gt;

&lt;p&gt;This is the trickiest one because even though we&#39;re passing on a complex, reactive object we&#39;d like to get all the changes &lt;i&gt;at once&lt;/i&gt; or &lt;i&gt;none at all&lt;/i&gt;. You might ask why would you want such a thing? The answer is quite simple: you&#39;d like to implement &quot;OK/Cancel&quot; functionality or (if the edits drive some kind of Ajax requests) limit the number of actions upon edits. It is quite obvious that there will be a need for a copy of the reactive object. For that I use &lt;code&gt;cloneDeep&lt;/code&gt; method from Lodash and it works just great so far.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;input v-model=&quot;internal.firstName&quot;&amp;gt;
    &amp;lt;input v-model=&quot;internal.lastName&quot;&amp;gt;
    &amp;lt;button @click=&quot;$emit(&#39;input&#39;, internal)&amp;gt;Save&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import cloneDeep from &#39;lodash/cloneDeep&#39;

export default {
  props: {
    value: Object
  },
  data () {
    return {
      internal: cloneDeep(this.value)
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if that component is used in the &lt;code&gt;ContactForm.vue&lt;/code&gt; (note the change from &lt;code&gt;:value&lt;/code&gt; to &lt;code&gt;v-model&lt;/code&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;{{ person.firstName }} - {{ person.lastName }}&amp;lt;/h1&amp;gt;
    &amp;lt;DataEdit &lt;b&gt;v-model=&quot;person&quot; @input=&quot;personUpdated&quot;&lt;/b&gt; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import DataEdit from &#39;./DataEdit.vue&#39;

export default {
  components: {
    DataEdit
  },
  data() {
    return {
      person: { firstName: &#39;John&#39;, lastName: &#39;Doe&#39; }
    }
  },
  methods: {
    personUpdated(newValue) {
      console.log(&#39;Person has been updated to: &#39;, newValue)
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;you won&#39;t see any changes to the header until they are &lt;i&gt;saved&lt;/i&gt; by clicking the &lt;code&gt;Save&lt;/code&gt; button. Pretty neat, right? On top of that you can be notified when the change occurred so if some additional action needs to take place (like updating list of people from an external database) by listening to the &lt;code&gt;input&lt;/code&gt; event. That is just pure awesome!&lt;/p&gt;

&lt;h3&gt;One more thing...&lt;/h3&gt;

&lt;p&gt;If the editor persists it will now share the internal and value objects which will make it behave like the case where everything is reactive. Not good - let&#39;s do something about it&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;input v-model=&quot;internal.firstName&quot;&amp;gt;
    &amp;lt;input v-model=&quot;internal.lastName&quot;&amp;gt;
    &amp;lt;button @click=&quot;$emit(&#39;input&#39;, internal)&quot;&amp;gt;Save&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import cloneDeep from &#39;lodash/cloneDeep&#39;

export default {
  props: {
    value: Object
  },
  &lt;b&gt;watch: {
    value: {
      handler (newValue) {
        this.internal = cloneDeep(newValue)
      },
      deep: true
    },
  },&lt;/b&gt;
  data () {
    return {
      internal: cloneDeep(this.value)
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The introduced &lt;code&gt;watch&lt;/code&gt; updates the &lt;code&gt;internal&lt;/code&gt; state so that it is again disconnected from the &lt;code&gt;ContactForm.vue&lt;/code&gt;. Of course in a situation where the &lt;code&gt;DataEdit.vue&lt;/code&gt; component is removed from DOM due to let&#39;s say closing a popup then the watch is completely unnecessary. It does however come in handy if there might be a possibility that the data object in question (or some of its parts) can be modified from the parent component. The internal state will be out of sync in such case. This might happen if some of the details come from an Ajax request or a timer. The &lt;code&gt;watch&lt;/code&gt; covers both cases so it is basically a universal way for data synchronization on changes from parent component.&lt;/p&gt;

&lt;h2&gt;Working example&lt;/h2&gt;

&lt;p&gt;I know this is a lot to take in at once. Therefore I have prepared a test application for you that illustrates all the pieces. You can find it at &lt;a href=&quot;https://github.com/padcom/vue-editor-components&quot;&gt;https://github.com/padcom/vue-editor-components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That&#39;s it, folks!&lt;/p&gt;

</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/7026676294334866406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/7026676294334866406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/7026676294334866406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/7026676294334866406'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/06/vuejs-editor-components.html' title='Vue.js - editor components'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-5340048305988917907</id><published>2018-04-09T20:49:00.000+02:00</published><updated>2018-06-23T14:07:55.421+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional"/><category scheme="http://www.blogger.com/atom/ns#" term="sfc"/><category scheme="http://www.blogger.com/atom/ns#" term="vue"/><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><category scheme="http://www.blogger.com/atom/ns#" term="vuejs"/><title type='text'>Vue.js and functional single file components</title><content type='html'>&lt;p&gt;Single file components (SFC) is probably the most powerful feature (structure-wise) in Vue.js. They are simple in nature but very powerful when it comes to bundling things together:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;h1 class=&quot;my-header&amp;gt;Hello!&amp;lt;/h1&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
}
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
.my-header {
  color: red;
}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are times when you want your component to be stateless. Such components are great for bundling together functionality that would otherwise be created by putting together other components. I call them template components, because they are predefined with places where you can override the defaults. Those components do not have state hence we call them stateless or functional.&lt;/p&gt;

&lt;p&gt;The problem with SFCs is that unlike regular .vue components they don&#39;t pass data down. Especially the &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;style&lt;/code&gt; properties are not passed automatically. To mitigate that I went through a few iterations to find the nicest solution. Here&#39;s what I came up with that seems to do the job very well. Let&#39;s assume we&#39;re creating a predefined component for animation. We want the styles to be bundled with the component so SFC is the right way to go.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
export default {
  functional: true,
  render: (h, { data, children }) =&gt; (
    &amp;lt;transition-group { ...data } tag=&quot;ul&quot; name=&quot;slide&quot;&amp;gt;
      { children }
    &amp;lt;/transition-group&amp;gt;
  )
}
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
.slide-move {
  transition: transform 1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A quick explanation: &lt;code&gt;{ data, children }&lt;/code&gt; is a destructing assignment from the second parameter to 2 fields that we&#39;ll use later. Then the &lt;code&gt;{ ...data }&lt;/code&gt; means &quot;apply all elements passed on (including but not limited to &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;style&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;That&#39;s all there is to it.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/5340048305988917907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/5340048305988917907' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5340048305988917907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5340048305988917907'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/04/vuejs-and-functional-single-file.html' title='Vue.js and functional single file components'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-5197790091431707185</id><published>2018-03-22T00:29:00.000+01:00</published><updated>2018-03-22T00:33:52.723+01:00</updated><title type='text'>HttpHandler registration on XSP4 vs IIS</title><content type='html'>&lt;h2&gt;The problem&lt;/h2&gt;

&lt;p&gt;You&#39;re developing an ASP.NET HttpHandler on Mono using XSP and now you need to deploy your app on IIS. What worked on XSP4 isn&#39;t working anymore and strange errors appear.&lt;/p&gt;

&lt;p&gt;Let&#39;s start with the config that works on XSP4&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;httpHandlers&amp;gt;
      &amp;lt;add verb=&quot;*&quot; path=&quot;*&quot; type=&quot;MyHandler&quot; /&amp;gt;
    &amp;lt;/httpHandlers&amp;gt;
  &amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But you put that same &lt;code&gt;Web.config&lt;/code&gt; file on IIS it throws errors.&lt;/p&gt;

&lt;h2&gt;The solution&lt;/h2&gt;

&lt;p&gt;As you see the registration happens inside &lt;a href=&quot;https://msdn.microsoft.com/en-us/LIBRary/bya7fh0a(v=vs.100).aspx&quot;&gt;&lt;code&gt;system.web/httpHandlers&lt;/code&gt;&lt;/a&gt; section. That works on XSP4 and older ASP.NET but it&#39;s not the case on modern IIS. In there you need to switch to &lt;a href=&quot;https://docs.microsoft.com/en-us/iis/configuration/system.webserver/handlers/&quot;&gt;&lt;code&gt;system.webServer/handlers&lt;/code&gt;&lt;/a&gt; section like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;

&amp;lt;configuration&amp;gt;
  &amp;lt;system.webServer&amp;gt;
    &amp;lt;handlers&amp;gt;
      &amp;lt;add name=&quot;name&quot; verb=&quot;*&quot; path=&quot;*&quot; type=&quot;MyHandler&quot; /&amp;gt;
    &amp;lt;/handlers&amp;gt;
  &amp;lt;/system.webServer&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&#39;s it! Happy coding!&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/5197790091431707185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/5197790091431707185' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5197790091431707185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/5197790091431707185'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/03/httphandler-registration-on-xsp4-vs-iis.html' title='HttpHandler registration on XSP4 vs IIS'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-4433130182547015738</id><published>2018-03-21T02:09:00.000+01:00</published><updated>2018-03-21T02:13:12.574+01:00</updated><title type='text'>Getting started with POI and React</title><content type='html'>&lt;p&gt;This will be a quick one and, quite frankly, a very obvious one. But since I forgot how it is done I better write it down for posterity (and me).&lt;/p&gt;

&lt;h2&gt;Setting things up&lt;/h2&gt;

&lt;p&gt;As always you&#39;ll need a folder. Let&#39;s call it &lt;code&gt;my-example&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ mkdir my-example
$ cd my-example&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we need to initialize our project:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ npm init&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and accept all the defaults.&lt;/p&gt;

&lt;p&gt;Next we need a few packages installed:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ npm install poi react react-dom --save-dev&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Creating &lt;code&gt;poi.config.js&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Since by default POI compiles JSX down to Vue&#39;s interpretation of what JSX is we need to tell it to use React&#39;s JSX compilation. We do that by adding the &lt;code&gt;poi.config.js&lt;/code&gt; file with the following content:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module.exports = {
  jsx: &#39;react&#39;
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Creating &lt;code&gt;start&lt;/code&gt; script&lt;/h2&gt;

&lt;p&gt;Finally, to make our project setup complete we should add a &lt;code&gt;start&lt;/code&gt; script to &lt;code&gt;package.json&lt;/code&gt; to make use of the locally installed POI:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&quot;scripts&quot;: {
  &quot;start&quot;: &quot;poi&quot;
}&lt;/pre&gt;&lt;/code&gt;

&lt;h2&gt;Time for a simple app&lt;/h2&gt;

&lt;p&gt;With all that setup all there is to it is to test it with some React components. For that we will create &lt;code&gt;index.js&lt;/code&gt; with the following content to display a &lt;i&gt;Hello, world!&lt;/i&gt;-type app:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import React from &#39;react&#39;
import ReactDOM from &#39;react-dom&#39;

ReactDOM.render(&amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;, document.getElementbyId(&#39;app&#39;))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And just like that, in under 3 minutes, by the magic of POI, we have a fully-working application that can be developed, tested and built for production deployment. I like it!&lt;/p&gt;

&lt;i&gt;Happy coding!&lt;/i&gt;


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/4433130182547015738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/4433130182547015738' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/4433130182547015738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/4433130182547015738'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/03/getting-started-with-poi-and-react.html' title='Getting started with POI and React'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-6936166459849605147</id><published>2018-03-21T00:42:00.003+01:00</published><updated>2018-03-21T00:42:32.580+01:00</updated><title type='text'>Big Fat Ass - Windows + Visual Studio</title><content type='html'>&lt;p&gt;&lt;b&gt;Warning: this post contains bad language, obscene descriptions and a lot of frustration. Don&#39;t read it if you&#39;re sensitive.&lt;/b&gt;&lt;/p&gt;

&lt;h2&gt;The fucking nightmare&lt;/h2&gt;
&lt;p&gt;In the past I used to work with Windows. I liked it - especially Windows 2000 and then XP. It was kind of fresh, you know? Still looking the same as the old win but kinda... better. And after a few small upgrades to the hardware, like a tiny bit more RAM, it worked really fast. I was reluctant to look for other OSes for more reasons than just &lt;i&gt;I got used to it&lt;/i&gt;: Delphi, the IDE I was working most of the time in, was not available on other platforms. And I loved Delphi. It was the best thing ever! Especially the Personal edition which was bloody fast and easy to use.&lt;/p&gt;

&lt;p&gt;At one point I gave Linux a try. Slackaware to be precise. I felt this was not just for me but also not for any sane human being. I mean come on: compile kernel just to be able to install the distro? Are you fucking kidding me? Then I gave RedHat a try. Well.. better but still: 24 floppies just to install the basic OS? Are you fucking kidding me?!!! And then Ubuntu came along a few years later. I ordered the CD (good old days :D), installed it and liked it instantly. It looked different, foreign... but nice. I got along with the keyboard quite fast, cmd was finally bash and way more humane to work with... Basically, for the first time I didn&#39;t immediately went with &quot;You have to be shitting me, man! What a shit hole!&quot;. But I was still a Delphi developer so it was more for entertainment than anything else...&lt;/p&gt;

&lt;p&gt;Fast forward a few years and that stopped being a problem since I moved to Java.&lt;/p&gt;

&lt;h2&gt;2018&lt;/h2&gt;

&lt;p&gt;It&#39;s 2018. I work exclusively in Linux, I love every bit of it. I like that I can choose not to butcher my computer with CPU/GPU-intensive operations just to show the content of a fucking folder. I&#39;m loving XFCE and everything about it. I use Linux Mint and my main occupation is frontend development so Windows is pretty much useless anyways. I play on Linux, I watch movies on Linux, I work on Linux. And everyone in my family does too and they like it! My distro of choice is Linux Mint because it is the closest approximation of Windows XP I can get out of the box. And it is good!&lt;/p&gt;

&lt;p&gt;And then I decided to give .NET a spin... Man,.. there are decisions that one regrets moments after they are made. At first it wasn&#39;t so bad. I still used Linux with Mono, tried Core but &lt;i&gt;it wasn&#39;t the right target I was looking for&lt;/i&gt; so Mono was the option. Everything seemed to work just fine, MonoDevelop rocks! Fast, easy, nice... I like. I even completed the entire project, was able to test it using XSP... &lt;/p&gt;

&lt;p&gt;All was good just up to the point where I needed to test it in real conditions. NOTHING FUCKING WORKED! NOT A SINGLE FUCKING THING! JAVA KILLER MY ASS!!!&lt;/p&gt;

&lt;p&gt;So basically creating a solution in MonoDevelop does not mean you will be able to load it into the latest Visual Studio. Windows, when I turned it on, immediately started taking over my CPU fan, spinning it so fucking fast the whole machine became more than just a bit warm. It was FUCKING HOT!!! And still... nothing fucking worked!!!&lt;/p&gt;

&lt;p&gt;After a trial and error, looking at Stack Overflow and other enlightened sites I finally was able to throw away all the project files, recreated them in VS 2017 and then it still didn&#39;t fucking work! All because some idiot decided to switch from one XML configuration section to another. I mean for the love of God, really?! WHAT THE FUCK!?!?&lt;/p&gt;

&lt;p&gt;It took me a better part of this evening to just get it started, then about 3 minutes to add a portion to my node module that converts from fucking backslashes to forward slashes (as though the rest of the fucking world were morons and used the wrong character for path separator) and I was finally on my marry to start hating Windows on my blog.&lt;/p&gt;

&lt;h2&gt;Post mortem&lt;/h2&gt;

&lt;p&gt;Unfortunately, as a front developer I need to have access to Edge which, surprise surprise!, is only available on fucking Windows. And this is the only reason I have a &lt;u&gt;separate, dual boot notebook&lt;/u&gt; that runs a legal (my God, what a fucking waste of fucking hard earned money) copy of Windows 10.&lt;/p&gt;

&lt;p&gt;I need a fucking drink after all this. No wonder .NET developers are so strange... there is a damn good reason for it!&lt;/p&gt;

&lt;p&gt;&lt;i&gt;God save us from Windows and .NET. Please!!!&lt;/i&gt;&lt;/p&gt;


</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/6936166459849605147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/6936166459849605147' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/6936166459849605147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/6936166459849605147'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/03/big-fat-ass-windows-visual-studio.html' title='Big Fat Ass - Windows + Visual Studio'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6245476510271728435.post-2929275399050530437</id><published>2018-01-29T00:23:00.001+01:00</published><updated>2018-01-29T00:23:35.922+01:00</updated><title type='text'>Side project: getting eyes far away</title><content type='html'>&lt;p&gt;Last year I became obsessed with FPV. I don&#39;t mean games - that&#39;s kinda for kids. I&#39;m talking here about getting an object, a plane in this case, equipped with a camera and other equipment that can be controlled from a distance. I was trying to get into the multi-rotor business but that seems not to be my thing. Planes, on the other hand, are. So I tried my luck there...&lt;/p&gt;

&lt;p&gt;My first time was... well... exciting wouldn&#39;t even begin to cover it! It was a mysterious experience! I was actually in a plane that flies around, hundreds of meters away from me, seeing the real life flashing before my eyes. It was simply a blast! But as soon as I flew the first time and saw the land that I already covered something woke up in me: the nagging question &lt;i&gt;what is out there&lt;/i&gt;? I guess I am kind of an explorer down deep inside :) And so I begun to cover more and more ground. It soon was pretty clear for me that the equipment I had at the time with a 200mW VTX was not going to quite cut it. All that was made crystal clear for me once I lost the plane after just several hundred meters flight in the neighborhood. It sucked big time and about 600 PLN was forever lost. Sometimes when I drive around I hope to see this plane hanging out in some tree but that didn&#39;t happen.&lt;/p&gt;

&lt;p&gt;Someone could say: this is way too expensive and too dangerous - but not me. I came back home, late at night that day, and immediately ordered a stronger VTX (used to ride a 200mW one, now I ordered a 600mW ImmersionRC that people said was good for several kilometers!). It took a while before I was able to get back up in the sky but it eventually happened. With the new VTX, a changed site and a new plane I was rocking the sky again!&lt;/p&gt;

&lt;p&gt;Over the course of last summer I didn&#39;t loose a plane (well, technically I did but more on that later or). I was flying first 1.3km to a landmark I knew and I was passionate to get to. That didn&#39;t work because of the antennas that I had. That day I learned that power is not everything - you need to have something to convey it with. And in the case of video transmission (and also the control transmission from your radio to the plane) antennas are the holy grail! So I went ahead and bought 3 of the most recommended (and most sexy) ones - the Aomway clover leave antennas. Alongside the 600mW VTX I also bought a 14dBi directional patch antenna. Using this setup I was finally able to easily break the 2km range!&lt;/p&gt;

&lt;p&gt;But my appetite (and the addiction) grew...&lt;/p&gt;

&lt;p&gt;So I started experimenting. First about going further than 2km. It turned out that the 100mW OpenLRS system wasn&#39;t all that good at ground leve.
 - so I built a 2m mast that gave me more range. A few weeks later I tested it up to 4.8km and let me tell you the wiggles that I have had that day were nothing compared to the first time with a woman! I was so fucking stressed out I almost fainted!&lt;/p&gt;

&lt;p&gt;All things considered it was a pretty good flight. I used a 3s 3000mAh Li-on pack at that flight and it &lt;i&gt;almost&lt;/i&gt; lasted to get the plane home. Just a few tents of meters over a field and the plane was safe and sound in my hands. That meant I needed more power. Lot&#39;s of it.&lt;/p&gt;

&lt;p&gt;In a situation like that power comes from a combination of input voltage, amps, ESC, motor and propeller. So I started looking for the best combination. Just out of share luck I have had a few od 2212 810kv motors around (from my failed attempt to build a 450-sized quadcopter). I thought, since it had the required max thrust (around 1kg) so why I don&#39;t I give it a shot. And so I did!&lt;/p&gt;

&lt;p&gt;The first attempt was very promising. At 4S and a 10x4.5 prop it flew great and I was able to finally reach the 5km mark. I turned back to see how the battery will behave on the way but it was plenty left. That encouraged me to give it another shot the next day and... that is how I achieved my up-to-date record of 8.2km out and safely back!&lt;/p&gt;

&lt;center&gt;&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/NLBIJbddzQw&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/center&gt;

&lt;p&gt;Oh boy was I excited! All my efforts were finally paying off! My dream was to take the plane from the place where I was usually flying back to the place I live - which was about 6.5km away. With the record flight of 8.2km I thought it was a no brainer. Man, was I wrong! It&#39;s not just the tx/rx/antennas combination but first and foremost the lay of the land that allows (or not) to get to longer distances. Luckily the day before that I have put my phone number and since the plane automatically landed on a busy street and a good man picked it up and called me the plane was recovered - and my ambition was greatly humbled.&lt;/p&gt;

&lt;p&gt;This year I&#39;m trying my luck in the same direction that my record flight of 8.2km was. I am hoping to break through the 20km barrier with some new equipment that I have bought:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;500mW Wolfbox TX (with potential to be modded to 1W)&lt;/li&gt;
  &lt;li&gt;1W VTx and a biquad 11dBi antenna that I tested up to 12km with crystal clear picture on the ground&lt;/li&gt;
  &lt;li&gt;an all new Mini Talon with 4S2P Li-on battery pack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The plan is as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First do a maiden of the plane with the minimum electronics to get it to fly&lt;/li&gt;
  &lt;li&gt;Add a flight controller for stabilization and get it to work as expected (F4 AIO FC with OSD)&lt;/li&gt;
  &lt;li&gt;Do a test flight over a 1km distance with the lest powerful antennas I have to check the viability of the video down and control up link&lt;/li&gt;
  &lt;li&gt;Do a endurance test with all equipment to see how long will the battery will last at what speeds - hope to get at least 40km range before the batteries are all dead)&lt;/li&gt;
  &lt;li&gt;Get back to the 5km mark and back&lt;/li&gt;
  &lt;li&gt;Get past the 10km mark and back&lt;/li&gt;
  &lt;li&gt;Get past the 15km mark and get back&lt;/li&gt;
  &lt;li&gt;Get past the 20km mark and get back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have no idea if this is going to work or not. I truly don&#39;t! But I hope one day I&#39;ll have a video to show you how the flight went and what emotions it gave me!&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Happy flying!&lt;/i&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://padcom13.blogspot.com/feeds/2929275399050530437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/6245476510271728435/2929275399050530437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2929275399050530437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6245476510271728435/posts/default/2929275399050530437'/><link rel='alternate' type='text/html' href='http://padcom13.blogspot.com/2018/01/side-project-getting-eyes-far-away.html' title='Side project: getting eyes far away'/><author><name>Matthias Hryniszak</name><uri>http://www.blogger.com/profile/11432592442831476478</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/NLBIJbddzQw/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry></feed>