Dutch Public Transport Digital Payment System (OV Chipkaart) – An Epic Fail Story for Me (and in general imho)
February 11, 2010 by Reboot · Leave a Comment
My horrible encounters with the system:
- Today was a pretty darn nippy morning (COLD!!! BrrrrRrRrRrrRrrrr), it’s take me a couple of minutes to get to the station. Arriving there the train was already coming, so I had to pick up pace to get in. When I swiped my card the ******* machine rejected it, WTF. It seemed the card itself had expired with 12 euros of credit still on it. Annoyed by that fact I was confronted with another fail, there wasn’t the opportunity to buy a single way ticket or a new card, WTF! So I had to call my wife to bring me to work. I later discovered that to reimburse my 12 euro credit on the expired card, it COSTS me 2,5 euro administration cost. That would probably be on top of the 7,5 euro which costs a new card.
I quote (sorry Dutch only, no translation available, seems they are lacking in the customer service department):
Defect?
Is uw persoonlijke of anonieme OV-chipkaart defect? In dat geval kunt u vragen om restitutie (teruggave) van uw saldo.
Bij een defecte persoonlijke OV-chipkaart, gebruikt u het formulier Beëindiging en restitutie van een persoonlijke OV-chipkaart.
U ontvangt het bedrag op uw bank- of girorekening (na aftrek van € 2,50 administratiekosten).
Restitutie is alleen mogelijk als er een saldo van minimaal € 5,00 op uw OV-chipkaart staat.
OV-chipkaart gestolen / verloren / defect / verlopen?
- Once I couldn’t check-out (a “wonderful” new feature, didn’t have to do that with the old paper card system) because the check-in/out device failed with a nice error message. Now my ride would cost 4 euros instead of 1,5. I had to wait in line for 20 minutes to get my money back.
- Some of the non-city stations have devices which allow both check-in and check-out. In the city area’s however, there are these small swinging doors you need to get through. One side is check-in, one is check-out. If you, by mistake, end up on the wrong side, you’re screwed! The first time that such a event happened to me my thought was: “no problem I’ll just swipe the card”, which would be OK for the non-city situation. The problem was however, I swiped against the check-out section, which costs me 4 euros, I thought I checked-in (yeah I didn’t look). When I exited from my ride I swiped to get out, for real this time, and again 4 euros disappeared from my card. Considering I don’t regularly use public transportation, I noticed it a couple of days later.
- I also accidentally carried two cards once and couldn’t remember which one I used to check-in. And there’s no way to find that out because the charging machines which show information about the card are behind the check-out. And yeah, I choose the wrong card … :(
- Another issue they experience is that people with a subscription of some sort (e.g. monthly) don’t check-in / check-out at all in trams. As long as they don’t enforce that they will miss out on a lot of valuable data which this system should have supplied.
- There are also issues because some of the transportation companies have different implementations, which for example means that using your subscription card at a specific buss company would result in loss of credit (hence the card holds both subscription and credit information!) instead of just registering the trip. Plus every company would charge it’s own “administration” fee, thus using different types of public transportation each being owned by a different company would create an additional cost.
- With this new system people are required to check-out. Checking-in rarely causes a queue, people simply don’t arrive all at the same time, getting out however causes everyone to queue up to get checked-out. Some stations have a limited supply of check-out machines or poorly placed ones. There’s also at least one person in the queue which is unable to check-out and tries repeatedly while holding up the queue, which might be incompetence or plain system failure.
I’m getting really annoyed by this system and even when it isn’t my fault it costs me time and money. Did we (poorly) re-invent the wheel here, I’ve seen much better systems abroad.
Oracle Tip: Ignoring case and diacritic differences in an Oracle search.
February 1, 2010 by Reboot · Leave a Comment
http://forums.oracle.com/forums/thread.jspa?threadID=14970
Instead of using the SQL UPPER and LOWER functions to perform case-insensitive queries, an alternative approach is to utilize the linguistic sort GENERIC_BASELETTER. GENERIC_BASELETTER groups all characters together based on their base letter values, this is achieved by ignoring their case and the diacritic differences.
Here is an example of a GENERIC_BASELETTER query.
ALTER SESSION SET NLS_COMP=ANSI; ALTER SESSION SET NLS_SORT=GENERIC_BASELETTER; SELECT * FROM PRODUCT WHERE PRODUCT_NAME = database;
All other operators, such as LIKE, perform comparisons in binary mode only. i.e. they do not honor the NLS_SORT value. This has now been be enhanced in 10gR2.
See also:
Diacritics in like clause, Globalization support
http://dbaforums.org/oracle/index.php?showtopic=915
Diacritics
http://en.wikipedia.org/wiki/Diacritic
Oracle® Database Globalization Support Guide
http://download.oracle.com/docs/cd/B14117_01/server.101/b10749/ch5lingsort.htm#i1006463
Oracle NLS_LOWER
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions098.htm#i78373
Oracle Replace
http://www.psoug.org/reference/translate_replace.html
SELECT translate('árvíztűrőtükörfúrógép','áéíóöőúüű','aeiooouuu') without FROM dual
Bug: Doctrine Oracle ID-Triggers.
February 1, 2010 by Reboot · Leave a Comment
Doctrine’s YAML created the following trigger to allow the creation of IDs via a sequencer.
Notice that the trigger name is not entirely upper-cased: USER_seq which in our case caused an error of the type: OCI_NO_DATA
CREATE OR REPLACE TRIGGER USER_AI_PK
BEFORE INSERT
ON USER
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
IF (:NEW.id IS NULL OR :NEW.id = 0) THEN
SELECT USER_seq.NEXTVAL INTO :NEW.id FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = 'USER_seq';
SELECT :NEW.id INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT USER_seq.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;
Oracle Tip: Apply RowNum after Order By
January 22, 2010 by Reboot · Leave a Comment
Ordering a resultset which contains a rownum statement will order the resultset which is return by the rownum.
e.g. the query:
select * from mytable where rownum <= 10 order by id desc
does not have to return the last 10 records.
See also:
http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
Think of it as being processed in this order:
1. The FROM/WHERE clause goes first.
2. ROWNUM is assigned and incremented to each output row from the FROM/WHERE clause.
3. SELECT is applied.
4. GROUP BY is applied.
5. HAVING is applied.
6. ORDER BY is applied.
*sighs* Refactoring a RIA application (again) to make it work for IE.
January 15, 2010 by Reboot · Leave a Comment
Ran into this one for example:
“The onchange event can be attached (inline or as an event handler) to any form element. It fires whenever the value of the form field changes. Unfortunately, the behavior is a bit strange in IE, in that for a checkbox, or a radio button field, the event doesn’t fire when it is supposed to (right when you click the option you want to choose), but instead it only fires, when you click elsewhere on the page/form, or if you explicitly call blur(); on the field.”
http://norman.walsh.name/2009/03/24/jQueryIE
Also got some styling issues with the jqGrid, and no, that’s NOT a **** up by jqGrid. It’s IE failing on proper CSS support, AGAIN.
Why do I even bother to make it fit for such a PATHETIC browser which is probably NEVER getting better.
I also yanked out the jQuery LiveQuery plug-in which should have increased performance instead of making it slower ?!?
Didn’t notice that in other browsers.
Toggle visibility jqGrid from outside the grid.
January 15, 2010 by Reboot · Leave a Comment
The only way I found working:
// Hide the grid when it is visible.
if ( $('#yourtableid).getGridParam('gridstate') == 'visible') {
$('#gview_yourtableid a.ui-jqgrid-titlebar-close.HeaderButton').trigger('click');
}
Any other thoughts on this are more than welcome!
Couldn’t find a jqGrid function to do it “properly” from outside the grid.
Setting the gridstate and refreshing didn’t work ?!?
Having fun in Lazytown.
January 15, 2010 by Reboot · Leave a Comment
My nickname is RebootGPF and no, that’s not my voice being frustrated :)
Bug: jQuery validation plug-in 1.6
Line 177 from the jQuery validation plug-in (1.6) contains:
this.settings = $.extend( {}, $.validator.defaults, options );
This line will actually cause a bug if the page contains multiple forms of which input elements have the same name.
What happens is that the defaults are not copied deep enough which leaves (at least one) reference to the properties in the defaults property.
The reference to the “rules” property will cause every created form validation to add rules to this “defaults.rules” property.
Hence some forms get unnecessary or unwanted rules.Fix it by changing line 177 into:
this.settings = $.extend(true, {}, $.validator.defaults, options );
Which performs a deep copy.
The next javascript snippet shows how a reference like this might cause issues (unless that’s what you really want).
$(document).ready(function() {
options = {
property : 'normal prop',
objectproperty : {prop1: 'prop1'}
};
var copy1 = $.extend({},options);
var copy2 = $.extend({},options);
//Adding to the objectproperty of the first copy will also alter the second :(
copy1.objectproperty.prop2 = 'prop2';
if (copy2.objectproperty.prop2) {
alert('Without deepcopy there might possibly be unwanted object references!');
}
if (options.objectproperty.prop2) {
alert('Hey look, also a new default option!');
}
});
$(document).ready(function() {
options = {
property : 'prop',
objectproperty : {prop1: 'prop1'}
};
// target = $.extend(true,{}, source1 , source2, ..., sourceN)
var copy1 = $.extend(true,{},options);
var copy2 = $.extend(true,{},options);
//alert('ready');
copy1.objectproperty.prop2 = 'prop2';
if (copy2.objectproperty.prop2) {
alert('Not the place to be!');
} else {
alert('Now we got a nice deep copy without leftover object references!');
}
});
Spotted: New version of the jquery-json plugin.
December 15, 2009 by Reboot · Leave a Comment
http://code.google.com/p/jquery-json/
Changes in Version 2.0
- The code has been re-written. It is now easier to read and follow; less of a mish-mash.
- Support for native JSON has been included. This means that if you are using a browser that supports JSON.stringify, it will be used. Also evalJSONand secureEvalJSON will use JSON.parse if available.
- Changes were made in the JSON output to move in line with the JSON object standard. This means 2.0 is not backwards compatible with the previous versions.
- toJSON now renders like compactJSON used to and compactJSON does not exist anymore. As per the JSON object standard, needless spaces are now removed. This makes it less readable; if someone wants to send me a prettyJSON patch, it will be welcome.
- Differences between output when JSON.stringify is available and when it is not could exist. I am unable to test all strings. Be aware when testing your apps.