It wouldn’t suprise me…

The DPP announced today a last minute addition to their ‘normal country’ draft resolution that ‘Chinese New Year’ will be renamed to ‘Taiwanese New Year’. This change comes on the heels of an amendment to drop the ROC Calendar in favor of the Gregorian Calendar. Party members at first had proposed scrapping the holiday altogether, but they ran into stiff opposition from those who were afraid of losing out on their week-long holiday. President Chen Shui-Bian was quoted as praising the move by saying, “Once we have a holiday named after Taiwan, A-Bian thinks it will be inevitable that other countries will recognize us as a normal country.”

Province of China (part 2)

I was looking for a site that could host a petition asking Kanye West to stop referring to Taiwan as a ‘Province of China’ when I came across iPetitions which looks like it would be a good place to post a petitions… except that it too calls Taiwan a ‘Province of China’.

So instead, I started a petition asking iPetitions to stop calling Taiwan a ‘Province of China’:

http://www.ipetitions.com/petition/ipetitions-taiwan/

Please click through and sign the petition. (And yes, if you’re in Taiwan you’ll have to select ‘Taiwan, Province of China’ as the country. Oh the irony.)

EDIT (2007-08-29 17:43): iPetitions has responded that they will be changing the listing but at this time the change has not been made. I will leave the petition up until the change is made.

Now that’s a nice response…

Occasionally I will register with or want to order products from a website only to find that they list something called ‘Taiwan, Province of China’ in their country list. Last week I got a newsletter from the Mises Institute about their new Bastiat Collection, a two volume set of the complete English translations of Frederic Bastiat’s writings. I was eager to order a set, as his writings have long been on my wish list but were a bit inconvenient to get previously. I was surprised to find that the Mises Institute also listed ‘Taiwan, Province of China’ in their online store. I sent a complaint to them and got back a very positive response a few days later, and quite emphatically at that:

Thank-you for bringing this matter to our attention. We have finally isolated the file and changed the Taiwan entry in our new e-commerce software’s database. We at the Ludwig von Mises Institute for Austrian Economics do not support the government of People’s Republic of China, or their policies, either directly or indirectly. Having Taiwan listed as “Taiwan Province of China” was nothing more than an oversight on our behalf as we continue to fix and customize our new software to our specific needs.

I couldn’t help but to support such a response by immediately ordering the Bastiat Collection as well as Freedom Under Siege by Ron Paul.

The Kanye West web site also lists ‘Taiwan, Province of China’ in their registration system but they have not responded to or corrected this after two weeks.

Web application development (part 4)

Et voila! My first application is complete. Since the last post I extended the edit module so that it would put in blank boxes for hours the store is open but for which there isn’t data already stored. (Actually I just have it put in entry boxes for everything from 8a to 11pm for every day, even though my Xingtian Temple restaurant is only open 10a-10p and Qingcheng restaurant is only open from 10a-10:30p on Saturday & Sunday. I’ll have to add in more smarts later so it will look at what hours the store is actually supposed to be open for.)

I encountered another couple of difficulties here, namely that when you add new inputs you have to also have a hidden form value for the foreign key id for the main table. So in my case since the main table is Daily and the multiple data fields are hourly, I have to have a hidden form value for data[Hourly][index][daily_id].

When it was editing existing fields this wasn’t a problem since it would figure out the missing values based on data[Hourly][index][id]. However when you are adding new stuff it is unable to make the connection and so the data gets stored without the foreign key and doesn’t get associated correctly. You also have to do the correct magic to create a new object when saving new (as opposed to updated) data, but that’s straightforward from the add example I referenced in part 3.

I also completed the add controller and add view with the ability to add the daily and hourly data all on one screen. This was actually quite straightforward once the edit stuff was done. Again, the main hitch is making sure you get the hidden field for the foreign key id in there or it won’t go in the db correctly.

The final piece was to give me a scheduling view. Basically I set up a scheduler controller and view under dailies which would take a store number, number of weeks and ending date of the schedule analysis. The last two are optional and default to 1 week and the date of the latest daily in the db for the store, respectively. It then will make up an average of units sold for each hour on each day (i.e. each of the Tuesday’s 8:00 sales averaged, etc.) and based on that would give a number of hours to schedule each employee.

I can’t describe it in much more detail than that because while this sort of calculation is common in food & beverage operations, the details of the method SUBWAY™ uses is proprietary. I’m still tweaking the algorithm on how to do the scheduling, but right now it’s roughly based on the Subway method with a few tweaks to make it look better to me. I also need to make the tweak parameters configurable in the database instead of hard coded in the code, but that’ll have to wait a bit.

It looks like I can cut down my morning and afternoon scheduling a bit and actually could use a bit more people at lunchtime than I had thought. But also overall it looks like I should be able to save quite a bit on labor costs with a more efficient schedule while at the same time improving service levels during busy times.

There’s a few other things I need to do. For example, there’s a fair amount of code that I probably should have put in the controller that I put in the view instead. I think I reverted to non-MVC programming practices quite a bit. I think from the MVC philosophy you shouldn’t be doing much more than displaying stuff in the view. Anything where it is calculating stuff should be in the controller. I also need to figure out how to modularize the code better.

But, hey, it works. Woo woo!

Web application development (part 3)

Well I didn’t quite get my first webapp done in time for last week’s meeting. Actually I got it mostly working, but the interface was not to my liking and I wasted a lot of time flailing about trying to figure out how to do what I wanted. I finally figured out how to do that so it shouldn’t be much longer before I have things completed.

Basically the issue is that I want to enter sales data for each day and each store. Each day has some data associated with the day over all, and then it also has breakdowns of specific data on an hourly basis. Or in CakePHP model lingo, stores hasMany dailies hasMany hourlies. The problem is that I want to view (index), add and edit the daily AND hourly data together on one form. The alternative is to enter the daily data, then add an hour, enter than data, add an hour… ad nauseum. There’s a limited and known amount of hourly data to enter, so it would be much easier to get it all over and done with in one form.

Getting the view to show dailies and hourlies together was straightforward. The scaffolding did a decent job of that by default so I was able to bake the scaffold view and modify it to my preference. The default data structure will automatically load the daily and related hourly data together when using the appropriate data loaders on properly associated models.

The editing/adding was a bit stickier. CakePHP’s form helper doesn’t handle this kind of thing at all currently. Basically if you aren’t editing a single row in a single table, you’re on your own, bub. The breakthrough was in finding this post on cake.php. It’s not exactly what I wanted, but it set me on the right track. The difference is they are editing multiple records from the same table together while I want to edit a single record from one table and multiple records from a related table together.

Fortunately the principle in both cases is similar. In my case I started with modifying the edit controller/view first. All the records I want to modify already were getting loaded automatically since the models had the proper associations set up. In my view I had to just loop over individual hours and set up form entries for each of them. Hour and id are hidden since those should not be changed.

The core of the edit view code to do this is as follows:

<?php foreach (array_keys($this->data['Hourly']) as $key):?>
<tr>

        <input type="hidden" name="data[Hourly][<?php echo $key; ?>][id]"
        value="<?php echo $this->data['Hourly'][$key]['id']; ?>" />

        <input type="hidden" name="data[Hourly][<?php echo $key; ?>][hour]"
        value="<?php echo $this->data['Hourly'][$key]['hour']; ?>" />

        <td><?php echo $pretty->hour($this->data['Hourly'][$key]['hour']);
                ?></td>

        <td>
        <input type="text" name="data[Hourly][<?php echo $key; ?>][hrtickets]"
        value="<?php echo $this->data['Hourly'][$key]['hrtickets']; ?>" />
        </td>

        <td>
        <input type="text" name="data[Hourly][<?php echo $key; ?>][hrgross]"
        value="<?php echo $this->data['Hourly'][$key]['hrgross']; ?>" />
        </td>

</tr>
<?php endforeach; ?>

It’s actually pretty straightforward conceptually, it was just getting the right incantation for it that was the problem, as this kind of thing is not covered in manual at all, and as mentioned, the forms helper doesn’t have code to do this kind of thing for you.

Then in the edit controller for dailies I originally had this (standard) code to save the modified data:

$this->Daily->save($this->data)

That will only save updates to the ‘Daily’ entries but not the ‘Hourly’ entries so I had to add:

foreach ($this->data['Hourly'] as $hourly) { $this->Hourly->save($hourly); }

This is a little bit simpler than the example in the above post. That’s because this is saving edits to existing data, so the ‘id’ field of each record is populated. In the add controller you need to do like the example in the post because the ‘id’ fields are empty in an add, so if you don’t create separate objects then the saves will just keep overwriting the first record over and over.

Anyways, the edit view and controller is already all set and working mostly the way I want it now. Getting the add view and controller working should be fairly simple at this point as that one is closer to the cake.php post I referenced. I might want to do something a bit fancy later by adding in forms for ‘missing’ hours in the edit, but that’s just spit and polish.

I’d be curious to know if the other MVC frameworks handle the case of adding/editing associated hasMany tables together in a more elegant manner?

Sepat Progress Report 3

Things have pretty much quieted down here. On the way home from checking in at my Qingcheng Restaurant I saw a small tree (really more like a sapling) in front of Nanjing E. Rd. MRT station knocked over, and there were at least two big trees down in Rongxing Park on the Minquan-Jianguo corner, one of which was covering the sidewalk. I also saw a branch down in front of the hospital at the corner of Minquan-Jilin. So looks like we did get some decent gusts earlier this morning even in the city. But it looks like those on the southside of Taipei in Xindian City, Muzha and Yangmei had a lot more excitement than we did, just from being a couple dozen km closer to the storm center.

Sepat Progress Report 2

Not too much to report in Taipei. It’s been gloomy most of the day but only occasional gusts and moderately heavy rainfall. The central part of the east coast got considerably more rain and wind. The current top rainfall for Taiwan is for an area in Hualian County which got 870mm (2′ 10 1/4″) of rain. No, that’s no an annual figure, that’s for this one storm.