tag:blogger.com,1999:blog-18328149059548736032024-02-19T00:21:56.145-08:00Coding Experiences with Qasim (QASH)Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-1832814905954873603.post-36892134114530557972014-12-28T06:56:00.001-08:002014-12-28T06:56:08.007-08:00CodeEval experience<div dir="ltr" style="text-align: left;" trbidi="on">
After <a href="http://community.topcoder.com/tc?module=MemberProfile&cr=22020968&tab=alg" target="_blank">Topcoder</a> and <a href="http://www.spoj.com/users/qasimzee" target="_blank">SPOJ</a>, <a href="https://www.codeeval.com/profile/qasimzee/" target="_blank">CodeEval</a> is so far going great in testing my problem solving skills. I started with hard problems and so far it's an interesting experience.<br />
<br />
I am also sharing this code on <a href="https://github.com/qasimzee/codeeval" target="_blank">github</a> in case anyone needs any explaination, please feel free to send me a message at ping@qasimzeeshan.com</div>
Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-1403189099054059302014-12-28T06:51:00.005-08:002014-12-28T06:56:39.768-08:00Qasim Zeeshan's new website<div dir="ltr" style="text-align: left;" trbidi="on">
Launched my <a href="http://www.qasimzeeshan.com/">new website</a> last month with few <a href="http://www.qasimzeeshan.com/blog">tech posts</a>. Please feel free to email me at <a href="mailto:ping@qasimzeeshan.com">ping@qasimzeeshan.com</a> in case you have anything to say.</div>
Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-81906394389047320452012-04-18T23:28:00.002-07:002012-04-18T23:44:37.956-07:00My approach to TCO 2012 Marathon competition<div dir="ltr" style="text-align: left;" trbidi="on">The problem statement is here: <a href="http://community.topcoder.com/longcontest/?module=ViewProblemStatement&rd=15099&pm=11859">http://community.topcoder.com/longcontest/?module=ViewProblemStatement&rd=15099&pm=11859</a><br />
<br />
My approach was pretty simple and concise. My solution extracts the strips from the extreme sides(top, bottom, left right) of the board and insert them to the strips with maximum whites(usually in the maximal component) those are not connected to their neighbouring strips. If they are connected to their neighbouring strips, no need to disturb them.<br />
<br />
After completing each line with whites, I used to check if all whites are connected using floodfill. Following are my scores (seed 1 to seed 10)and output images:<br />
<br />
1) 83.25 <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgJ7qpfOs2M_myelPnGoJbbxubEuYWyK0lWJVJCeqRqy9RsiXdhWfo0DTCotdvuJa-7u1n3c6dRgzoR4HhabZEFkRqqTRbVUto9cVtifRt1N9znPU7x86MQctf5iSaTgufIdcFTTr4PVw/s1600/seed1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgJ7qpfOs2M_myelPnGoJbbxubEuYWyK0lWJVJCeqRqy9RsiXdhWfo0DTCotdvuJa-7u1n3c6dRgzoR4HhabZEFkRqqTRbVUto9cVtifRt1N9znPU7x86MQctf5iSaTgufIdcFTTr4PVw/s320/seed1.PNG" width="320" /></a></div><br />
2) 87.85609934258582 <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjWBIds0SyaRvFXLi3NvTF57hZ_9abkMqOXNS3sJ9gv32z_MBMiAWFKEpGzICaPnI827aOJ0eM3fsiF5wY8sZJeYNUPC6v8l1dJ-Bp6jXPFQxz01d1Hj2aRqmM2hreBziyrsWu9XxIINo/s1600/seed2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjWBIds0SyaRvFXLi3NvTF57hZ_9abkMqOXNS3sJ9gv32z_MBMiAWFKEpGzICaPnI827aOJ0eM3fsiF5wY8sZJeYNUPC6v8l1dJ-Bp6jXPFQxz01d1Hj2aRqmM2hreBziyrsWu9XxIINo/s320/seed2.PNG" width="320" /></a></div><br />
3) 81.49243918474689 <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEmlMD6YdJq1pqbJXB1j0HzJx2iTWfseD7OkuiGT5xSzHvla7iPgV5WPJaX23T2KRzzgyxYVM1VdpytstBRlnwdtEOidRHqsPFw9iGceJ9xrLhSIHivjbwxb_p1eIHYzwGtP10dw0HWX0/s1600/seed3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEmlMD6YdJq1pqbJXB1j0HzJx2iTWfseD7OkuiGT5xSzHvla7iPgV5WPJaX23T2KRzzgyxYVM1VdpytstBRlnwdtEOidRHqsPFw9iGceJ9xrLhSIHivjbwxb_p1eIHYzwGtP10dw0HWX0/s320/seed3.PNG" width="320" /></a></div>4) 81.43961927424152 <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhlh4B7hxHNfZydcs48M_NKXdeFcD2PTNcbZn1P-ZzmF84dXjl54fNy745Q7x4fWCqsMXpAnz5bE8CZLV9xTZ3ncu0oZIhb_XLR2AgO8MtBdIFbn3yJ6ogbO3ziLnxII496nEexQhyaDA/s1600/seed4.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhlh4B7hxHNfZydcs48M_NKXdeFcD2PTNcbZn1P-ZzmF84dXjl54fNy745Q7x4fWCqsMXpAnz5bE8CZLV9xTZ3ncu0oZIhb_XLR2AgO8MtBdIFbn3yJ6ogbO3ziLnxII496nEexQhyaDA/s320/seed4.PNG" width="320" /></a></div><br />
5) 67.22552731206058 <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF7wlicAiuZ_J4bIgERz8_C4Jt5NZeUWiur6JaNQhKVOPZhcqDrgJ1Jy8FTpfDz6ALAqR5AoJkPgCNcmh_9lpvmhh0ZML7MYWZdfCBn6zrpMYVVb7CPeybv_jfhAN_OsKfWd7OBMsj3kA/s1600/seed5.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF7wlicAiuZ_J4bIgERz8_C4Jt5NZeUWiur6JaNQhKVOPZhcqDrgJ1Jy8FTpfDz6ALAqR5AoJkPgCNcmh_9lpvmhh0ZML7MYWZdfCBn6zrpMYVVb7CPeybv_jfhAN_OsKfWd7OBMsj3kA/s320/seed5.PNG" width="320" /></a></div><br />
6) 82.146399523904<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsPta8AyAxLt4TngE5blfU0_CNiUhDt7qVUgsMbBsVtmueE3esAjG3Y10EIk_pOEt2fYp3xS7UHBdFX-n2LwZMnBsIjNwZrUDPH-ndwzWTCEOu4nB_ifalG3f_-1akkx-jfmYvVKtv-Kg/s1600/seed6.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsPta8AyAxLt4TngE5blfU0_CNiUhDt7qVUgsMbBsVtmueE3esAjG3Y10EIk_pOEt2fYp3xS7UHBdFX-n2LwZMnBsIjNwZrUDPH-ndwzWTCEOu4nB_ifalG3f_-1akkx-jfmYvVKtv-Kg/s320/seed6.PNG" width="320" /></a></div><br />
7) 81.375<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_lZGyyxb4P5KpbF8LpvuFZalN0s00snBIvDz2UFMR-RwflAldcchTfhMqYe5RaAGc_paQ32JE7UG7leIG-x8oBfkkCp7vg3Oqi8gDWsywhzZ8EtV5TBYpWpgHzhU6jO7VxR-j6grGW2Y/s1600/seed7.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_lZGyyxb4P5KpbF8LpvuFZalN0s00snBIvDz2UFMR-RwflAldcchTfhMqYe5RaAGc_paQ32JE7UG7leIG-x8oBfkkCp7vg3Oqi8gDWsywhzZ8EtV5TBYpWpgHzhU6jO7VxR-j6grGW2Y/s320/seed7.PNG" width="320" /></a></div><br />
8) 81.77083333333334<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKDLUehxd3aNdkomnBsxBWuLsrbZV5rOoUd5VRIuOO6__VcM926EgtR5EpXEC9ft-pYt8QmbmFbPIPBI5FlfSJzZ41AQ4tC9UZ-9t_dHNbdQfLR2S6ftp5S99hquiSckxpYx01KLKwlZA/s1600/seed8.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKDLUehxd3aNdkomnBsxBWuLsrbZV5rOoUd5VRIuOO6__VcM926EgtR5EpXEC9ft-pYt8QmbmFbPIPBI5FlfSJzZ41AQ4tC9UZ-9t_dHNbdQfLR2S6ftp5S99hquiSckxpYx01KLKwlZA/s320/seed8.PNG" width="320" /></a></div><br />
9) 87.23072562358276<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6MRU6nthZfcIYsoXXGFwPiVNOjvqMLrIPK6me0poSw5ZlD9PlrtCeGXqwe4XVmRlZwaXxUWIdEXQd33Uczu9bxZMgpi4fWDY7AEluNHKk7P7IjViX3QcrYEF3mEsy4z5KKyaHfccM7Yo/s1600/seed9.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6MRU6nthZfcIYsoXXGFwPiVNOjvqMLrIPK6me0poSw5ZlD9PlrtCeGXqwe4XVmRlZwaXxUWIdEXQd33Uczu9bxZMgpi4fWDY7AEluNHKk7P7IjViX3QcrYEF3mEsy4z5KKyaHfccM7Yo/s320/seed9.PNG" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;">10) 82.42832606685162 </div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZBoYYik_tCe0C8Lg25YQsuO7qTRUJt7spZFwbrizlvHpOtrVt8ClgfPz-Vt-dfr3xGarq7Vdkgm7WA4GDfs7M50NXDW6NoUj_vbH_qPzblDnN-JQpFPxgjzhC1AGuR7PN0vYuUREwO0/s1600/seed10.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZBoYYik_tCe0C8Lg25YQsuO7qTRUJt7spZFwbrizlvHpOtrVt8ClgfPz-Vt-dfr3xGarq7Vdkgm7WA4GDfs7M50NXDW6NoUj_vbH_qPzblDnN-JQpFPxgjzhC1AGuR7PN0vYuUREwO0/s320/seed10.PNG" width="320" /></a> </div><br />
Complete standings can be found on <a href="http://community.topcoder.com/longcontest/?module=ViewStandings&rd=15099">http://community.topcoder.com/longcontest/?module=ViewStandings&rd=15099</a></div>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-56897354341145445952011-04-26T01:28:00.000-07:002012-01-19T02:18:25.647-08:00Creating Drupal CCK field module.<div dir="ltr" style="text-align: left;" trbidi="on"><span class="Apple-style-span" style="color: #3f3e29; font-family: Arial, Helvetica, sans-serif; font-size: 14px; line-height: 18px;"></span><br />
<div class="field field-type-text field-field-byline"><div class="field-items"><div class="field-item odd"><div class="field-label-inline-first" style="display: inline; font-weight: bold;">By: </div> Jennifer Hodgdon (<a href="http://www.poplarware.com/articles/cck_field_module">http://www.poplarware.com/articles/cck_field_module</a>)</div></div></div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">When setting up a site using the <a href="http://drupal.org/" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Drupal</a> content management system, you'll often find that you need to define content types that have fields attached to them, beyond the default Title and Body. In Drupal version 7.x and later, this field functionality is planned to be in the core distribution of Drupal, but in 6.x and previous versions of Drupal, it is provided by the contributed <a href="http://drupal.org/project/cck" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Content Construction Kit (CCK) module</a> and the many associated modules that provide additional field types for CCK.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For some sites, you may find that you need to define fields that have multiple values; for example, you might want to place several images along the right side of a page (each one being an Image field). That is no problem, in itself -- CCK allows you to set any field to accept multiple values, and in version 2 of CCK, you can easily re-order, delete, and add new items to the list using a very nice AJAX interface.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">But what if you need to associate, for instance, a caption and a taxonomy term with each of those images? Or in other words, what if you want to <strong style="font-weight: bold;">add fields to your content type as a group</strong>? With the current CCK version, you have<strong style="font-weight: bold;">several choices of how to do that</strong>:</div><ol style="list-style-type: decimal; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><strong style="font-weight: bold;">Several separate fields:</strong> Create a multiple-valued field for the image, another for the caption, and another for the taxonomy term, and tell the people editing content on the site to try to keep them synchronized. This is not really workable in general -- users would need to scroll up and down the content entry screen to do their data entry, and inevitably someone will make a mistake and you'll have a caption or term associated with the wrong image. Also, for this specific case, Content Taxonomy as a multiple-valued field just gives you one multi-select list, so there is no way to choose a given taxonomy term more than once, or indicate the order (term 1 goes with image 1, etc.).</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><strong style="font-weight: bold;">Content sub-type</strong>: Create a second content type "Image Caption Term" to hold an image and its associated data. Then add a multiple "Node Reference" field to your original content type, which will associate your page with its images. This can be made to work, but in practice the editing is at best clumsy. (The <a href="http://drupal.org/project/modal_noderef" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Modal Nodereference</a>module may help in making the editing less clumsy.) Also, you'll end up with a lot of these little "Image Caption Term" items cluttering up your content management screens, which will confuse novice users.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><strong style="font-weight: bold;">Content Multigroup module:</strong> Try out an <a href="http://drupal.org/node/494100" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">experimental "Content Multigroup" module</a> that is supposed to let you group multiple CCK fields together. As of this writing (April 2010), this module is not stable (not even released as an "alpha" version), and last time I tried it (October 2008), it didn't work at all with image fields. It may have improved since then.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><strong style="font-weight: bold;"><a href="http://drupal.org/project/flexifield" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Flexifield Module</a></strong>: This may be working better now than the last time I tested it (October 2008).</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><strong style="font-weight: bold;">Custom CCK field:</strong> Create your own custom CCK field module that contains the desired grouping of information. Doing this is not very difficult, works very well, and is the <strong style="font-weight: bold;">subject of this article</strong>.</li>
</ol><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">With that motivation, in this article I describe how to create a module that implements a custom "compound" or "grouped" CCK field for Drupal 6.x and CCK 2.x. The article shows two examples, both of which allow you to add the field to a CCK content type as a multiple-valued field, which will allow a content editor to add, edit, delete, and re-order all this information as a group. The two examples in this article (both of which can be downloaded below):</div><ol style="list-style-type: decimal; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a class="leftimg" href="http://www.poplarware.com/sites/poplarware.com/files/page_images/cckfield.jpg" style="color: #679046; float: left; font-style: italic; font-weight: bold; margin-bottom: 0.1in; margin-left: 0in; margin-right: 0.25in; margin-top: 0.1in; text-decoration: underline;" title="Click to see screen shot"><img alt="small screen shot" src="http://www.poplarware.com/sites/poplarware.com/files/imagecache/mini_thumb/page_images/cckfield.jpg" style="border-bottom-width: 0px; border-color: initial; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-style: initial; border-top-width: 0px;" /></a> A compound <strong style="font-weight: bold;">image, caption, and taxonomy field</strong>: Allows a user to upload an image, provide "alt" and "title" text for the image, enter a caption (arbitrary HTML text), and choose one or more taxonomy terms. You can click the image to the left to see what it looks like in action.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">A simpler <strong style="font-weight: bold;">person field</strong>, with fields for displayed name, job title, phone number, and email address, which you could use if you didn't want to have full nodes for each "person". It also provides an illustration of how to make a compound field that contains just simple text fields.</li>
</ol><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;"></div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">If you need the exact functionality of one of the two examples here, you can just use the modules I created (download them below) -- they should work. If you need a different set of fields, you should be able to follow the steps in this article to create your own compound CCK field. I'd also recommend checking out the <a href="http://drupal.org/project/link" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Link module</a> as an example.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">If creating your own Drupal module is beyond you, you can also hire Poplar ProductivityWare to create a module for your Drupal site -- click here to <a href="http://www.poplarware.com/contact" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">contact Poplar ProductivityWare</a>.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Here's what this article contains:</div><a href="http://www.blogger.com/post-edit.g?blogID=1832814905954873603&postID=5689735434114544595" name="contents"></a><br />
<ul style="list-style-type: disc; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Introduction and Motivation (above)</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://www.poplarware.com/articles/cck_field_module#start" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Getting Started</a></li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://www.poplarware.com/articles/cck_field_module#field" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Defining the Field</a></li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://www.poplarware.com/articles/cck_field_module#widget" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Defining the Widget</a></li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://www.poplarware.com/articles/cck_field_module#formatter" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Defining the Formatter and Theming</a></li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://www.poplarware.com/articles/cck_field_module#details" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Final Details</a></li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><a href="http://www.poplarware.com/articles/cck_field_module#further" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Downloads, Background, and References</a></li>
</ul><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">To understand this article, you will need a basic understanding of PHP, Drupal and its terminology, Drupal module development (hooks, Forms API, and basic module file structure), and the CCK and Views modules (i.e. how to define content types and views -- you don't need to know all about the inner workings of the modules). Check the<a href="http://www.poplarware.com/articles/cck_field_module#further" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Downloads, Background, and References section</a> below for more information, if you encounter terminology or concepts that you are unfamiliar with. The completed module is also provided as a download in that section of the article -- it is GPL licensed, so you can use it and modify it as you wish under the terms of the license. You might want to download it now so you can refer to it as you read this article. The actual module code has more comments, and a couple of functions that were omitted from the article.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">And before going any further, I'd like to thank Josh Kopel of Kolaboration Studio, who sponsored part of the development of the initial image/caption/taxonomy field module and the original article.</div><hr style="background-color: #679046; border-bottom-color: rgb(103, 144, 70); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(103, 144, 70); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(103, 144, 70); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(103, 144, 70); border-top-style: solid; border-top-width: 1px; color: #679046; height: 4px;" /><a href="http://www.blogger.com/post-edit.g?blogID=1832814905954873603&postID=5689735434114544595" name="start"></a><br />
<h2 style="font-size: medium; font-weight: bold; line-height: 1.3em; margin-bottom: 0.667em; margin-top: 0.667em;">Getting Started</h2><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The first step in creating our module is to choose some names:</div><ol style="list-style-type: decimal; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">The first module we are creating implements a compound CCK field for an image, caption, and taxonomy term. So, I have chosen to call the CCK field "Image Caption Taxonomy", with machine-readable name "img_cap_tax". To distinguish the name of the CCK field from the name of the module, I have chosen to call the module "Image Caption Taxonomy Field", and to use the machine-readable name "img_cap_tax_fld" for the module; I'll refer to this machine-readable name as "(module)".</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">The second module is for a person field, so the CCK field will be called "Person", with machine readable name "person". The module will be "Person Field", with machine readable name "person_fld".</li>
</ol><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Below, when you see "(field)", it refers to the machine-readable name of the field, and "(module)" refers to the machine-readable name of the module.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Next, we need to create files "(module).info" and "(module).module", in order for this to be a Drupal module. A couple of notes:</div><ul style="list-style-type: disc; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Because this module implements a CCK field, we can rely on the CCK module to take care of all the database tables for us. For that reason, we don't need a .install file for this module to define the database schema.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">We do need to define some module dependencies in the .info file, as we will see below. Check the completed .info file in the module download for a list.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">It is possible to define multiple CCK fields in a single module. However, having done it once, I really wouldn't recommend it -- it makes the module file confusing, and less "modular" (i.e. someone might only need one of your fields, but have to load the entire module with several fields in order to get that functionality on their site).</li>
</ul><hr style="background-color: #679046; border-bottom-color: rgb(103, 144, 70); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(103, 144, 70); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(103, 144, 70); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(103, 144, 70); border-top-style: solid; border-top-width: 1px; color: #679046; height: 4px;" /><a href="http://www.blogger.com/post-edit.g?blogID=1832814905954873603&postID=5689735434114544595" name="field"></a><br />
<h2 style="font-size: medium; font-weight: bold; line-height: 1.3em; margin-bottom: 0.667em; margin-top: 0.667em;">Defining the Field</h2><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Now that we have our files created, the next step is to implement some core and CCK-specific hooks that tell CCK about our field. These hook implementations go into the (module).module file.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_field_info()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">First, we'll give CCK the field's machine-readable name, human-readable name, and a longer description, by implementing the CCK hook_field_info(). In the first example (the second example is nearly the same):</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_field_info() {
return array(
'img_cap_tax' => array(
'label' => t('Image Caption Taxonomy'),
'description' => t('Stores an image file, text for alt and title tags, a caption, and a taxonomy term'),
)
);
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">As you can see, the return value for hook_field_info() is an associative array, keyed on the machine-readable name of the CCK field we are defining. Each element of the returned array is an associative array, with components 'label' giving the human-readable name of our field, and 'description' giving a more verbose description. And since all human-readable text in Drupal modules should be internationalization-ready, we enclose it in the t() function.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">Core hook_install(), hook_uninstall(), hook_enable(), hook_disable()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Next, we will implement the core Drupal hook_install(), hook_uninstall(), hook_enable(), and hook_disable() so that our field will be properly added and removed from Drupal and CCK. These all work the same way: we just tell Drupal to let CCK handle the process through its content_notify() function, which takes care of all of the details. For example, here is the function for the core Drupal hook_install():</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_install() {
content_notify('install', 'img_cap_tax');
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The other three hooks are exactly the same -- just substitute "uninstall", "enable", or "disable" for "install". Note that it is possible to put these functions into a module's (module).install file instead of (module).module, but since they are so small in this case (and we have nothing else to go in the (module).install file), I've chosen to leave them in (module).module.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">One other detail: these functions are calling the CCK module function content_notify() directly. So, we need to make sure that function is loaded when we call it:</div><ul style="list-style-type: disc; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Make our module dependent on the CCK module (whose machine-readable name is "content") -- that dependency goes into the .info file.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Verify which file the content_notify() function is defined in -- if it had been in an include file rather than the main .module file, we would have needed to put an include directive in the hook_init() implementation in our module.</li>
</ul><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;"></div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">We'll need to do this for other module functions we'll be calling directly later in this article, so I'll just suggest that you look at the completed module's .info file (or the <a href="http://www.poplarware.com/articles/cck_field_module#further" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">reference section below</a>) to see the module dependencies, and the img_cap_tax_fld_init() function (implementation of hook_init() ) to see what include files we needed to load explicitly.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_field_settings()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Now, we need to tell CCK about the "settings" for this field, using CCK hook_field_settings(). This is a sort of catch-all hook for CCK, with several "operations", each one letting our field module give a different piece of information to CCK. The example CCK field based on an image needs to behave very similarly to the Image field from the existing ImageField module. That field, in turn (in the current implementation of ImageField) is actually just a FileField file field, with a special "widget" and "formatter" (see sections below) that makes it show as an image rather than a file. So, for the first example field, we will borrow heavily from the FileField module in our field settings function. For the operations that need to do something different from FileField, we'll call into other functions, which are described in the next section. Here's the function:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_field_settings( $op, $field ) {
switch( $op ) {
case 'form':
return img_cap_tax_fld_field_settings_form( $field );
case 'save':
return img_cap_tax_fld_field_settings_save( $field );
default:
return filefield_field_settings( $op, $field );
}
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">(Of course, we'll need to make sure that FileField is a dependency of this module, as described above.)</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For the second example, which is built up of text fields, we need to do something slightly different, because we don't have the FileField module around to help us with settings. We don't need any settings for this field, but we do need to define the database storage:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_field_settings($op, $field) {
switch ($op) {
case 'database columns':
$columns['displayed_name'] = array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'sortable' => TRUE, 'default' => '');
$columns['job_title'] = array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'sortable' => TRUE, 'default' => '');
$columns['phone'] = array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'sortable' => FALSE, 'default' => '');
$columns['email'] = array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'sortable' => FALSE, 'default' => '');
return $columns;
}
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For another example of a text-based field, but which has a settings form, you can check out the <a href="http://drupal.org/project/link" style="color: #679046; font-style: italic; font-weight: bold; text-decoration: underline;">Link module</a>.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">filefield_field_settings() Operations Functions (image example only)</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The next step (for the image field example only) is to define the individual operations functions that are called from the field settings function in the previous section. By convention, in this module the functions are located in an include file, (module)_field.inc. Let's start with the <strong style="font-weight: bold;">"form" and "save" operations</strong>, which define the field settings form the user can use to customize the field (apart from the sections already provided by the FileField module), and which fields in the settings form should be saved to the database. There is also a <strong style="font-weight: bold;">"validate"</strong> operation, which lets you run checks on the submitted data, but we don't need anything beyond what FileField does for this, so I won't describe that here.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In our field settings form, we want to do start with what the FileField module does for its field, add in most of what the Content Taxonomy module does for its field, and also allow the user to choose between plain text and having an Input Format (filtered) for the caption field.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">We'll also make a couple of changes to what Content Taxonomy does. First, Content Taxonomy has a setting that allows you to take the taxonomy choices from its field and apply them to the node as a whole. We won't allow for that option on our field, as it doesn't make sense in a compound field. Second, we also want to let the user choose whether the taxonomy term is optional, and whether it should be multiple-valued. We will also add some fieldsets to the form for grouping.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">So, with all of that motivation, here are our "form" and "save" operations functions:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_field_settings_form( $field ) {
$form1 = filefield_field_settings( 'form', $field );
$form2 = content_taxonomy_field_settings( 'form', $field );
$form2['save_term_node']['#type'] = 'hidden';
$form2['taxonomy_group'] = array(
'#type' => 'fieldset',
'#title' => 'Taxonomy',
'#collapsible' => 0,
);
$form2['taxonomy_group']['vid'] = $form2['vid'];
unset( $form2['vid'] );
$form2['taxonomy_group']['allow_multiple'] = array(
'#type' => 'checkbox',
'#title' => t('Allow multiple taxonomy terms'),
'#default_value' => is_numeric($field['allow_multiple']) ? $field['allow_multiple'] : 0,
'#description' => t('If this option is checked, the user can select multiple taxonomy terms for each image; otherwise, at most one.'),
);
$form2['taxonomy_group']['required_term'] = array(
'#type' => 'checkbox',
'#title' => t('Taxonomy required'),
'#default_value' => is_numeric($field['required_term']) ? $field['required_term'] : 0,
'#description' => t('If this option is checked, the user must select at least one taxonomy term for each image; otherwise, it is optional.'),
);
$form2['hierarchical_vocabulary']['#weight'] = 100;
$form3 = array( 'text_processing' => array(
'#type' => 'radios',
'#title' => t('Text processing for Caption'),
'#default_value' => is_numeric($field['text_processing']) ? $field['text_processing'] : 0,
'#options' => array( 0 => t('Plain text'), 1 => t('Filtered text (user selects input format)')),
));
return $form1 + $form3 + $form2;
}
function img_cap_tax_fld_field_settings_save( $field ) {
$flds1 = filefield_field_settings( 'save', $field );
$flds2 = content_taxonomy_field_settings( 'save', $field );
$flds2[] = 'allow_multiple';
$flds2[] = 'required_term';
$flds3 = array( 'text_processing' );
return array_merge( $flds1, $flds2, $flds3 );
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">There is also a hook_field_settings() operation for <strong style="font-weight: bold;">"database columns"</strong>, where you can define the database columns that CCK will use to store your field's data (you can see this in the second example above). For the image-based field, however, the FileField module creates a serialized "data" field in the database for us to use. We'll put all of the alt, title, caption, and taxonomy information into the "data" array, so we don't have to add any additional database columns.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Finally, there is a hook_field_settings() operation for <strong style="font-weight: bold;">"views data"</strong>, which allows a CCK field to return information about how it can be used for sorting and filtering in the Views module. (Any CCK field can automatically be included as a Field in Views, so we don't have to worry about that.) Keeping in mind that our field is mainly useful if it is added to a content type as a multiple-valued field (otherwise, you wouldn't really need a compound field), probably <i>sorting</i> the nodes in a view based on some aspect of this field doesn't really make sense. However, I can envision <i>filtering</i> a view using this field in a couple of ways:</div><ul style="list-style-type: disc; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Whether or not the content has at least one image attached to it. This should come from the FileField module.</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Whether a particular taxonomy term is present or not.</li>
</ul><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">As of this writing, this hasn't been implemented. Sorry!</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_field()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The next set of things we need to define is included in CCK hook_field(), which basically tells CCK if it needs to do anything special when a the field is loaded from or saved to the database. For the image field example, there is a special action: move the image file from its temporary location to a permanent location, and make note of that location in the database field (the FileField module has a function that does this). Also, all text fields need to be "sanitized", for both field examples, according to the input format (i.e. make sure it contains only the allowed HTML tags, or no text if the input format is plain text). And the email address in the person field example needs to be validated. All of these are operstaions in hook_field().</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For the first (image) field example, here's the hook_field() implementation, which calls a function we'll define below for the "sanitize" operation, and lets FileField handle the rest:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_field($op, $node, $field, &$items, $teaser, $page) {
if( $op == 'sanitize' ) {
img_cap_tax_fld_field_sanitize( $node, $field, $items, $teaser, $page );
}
return filefield_field( $op, $node, $field, $items, $teaser, $page );
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In our "sanitize" operation function, we will do pretty much what the Text field module in CCK does to sanitize text fields: figure out which input format was chosen, filter using that input format, and save the result with a "safe" prefix so it can be used for theming. Here is the function (I've put it into the (module)_field.inc file):</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_field_sanitize($node, $field, &$items, $teaser, $page) {
$isplain = empty( $field['text_processing'] );
$check_access = is_null( $node ) ||
( isset($node->build_mode) && $node->build_mode == NODE_BUILD_PREVIEW );
foreach( $items as $delta => $item ) {
$dat = $item['data'];
if( !is_array( $dat )) {
$dat = unserialize( $dat );
}
$text = isset( $dat['caption'] ) ? $dat['caption'] : '';
if( $isplain ) {
$text = check_plain( $text );
} else {
$text = check_markup( $text, $item['format'], $check_access );
}
$items[$delta]['safe_caption'] = $text;
}
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">One detail to note here is that I found that the "data" array from FileField is sometimes coming into this function in a serialized format (I'm not sure exactly why). So this function checks to see whether it needs to be unserialized before making use of it.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In the second example, as we mentioned, we need to support sanitation and validation. The validation checks to see whether the email address is in a valid format, and the sanitation ensures that only plain text has been entered for the other field components. Here's the function:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_field($op, &$node, $field, &$items, $teaser, $page) {
switch ($op) {
case 'validate':
if (is_array($items)) {
foreach ($items as $delta => $item) {
if ($item['email'] != '' && !valid_email_address(trim($item['email']))) {
form_set_error($field['field_name'],t('"%mail" is not a valid email address',array('%mail' => $item['email'])));
}
}
}
break;
case 'sanitize':
foreach ($items as $delta => $item) {
foreach ( $item as $col => $dat ) {
$items[$delta]['safe_' . $col ] = check_plain($item[ $col ]);
}
}
break;
}
}
</pre><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_content_is_empty(), hook_default_value()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">There are a few more pieces of information CCK needs about our fields: how to tell if it is "empty" of information (CCK hook_content_is_empty() ), and what the default value should be (CCK hook_default_value() ). In the first example, since the primary component of our field is an image, we will say that the field is considered "empty" if it has no image file, and we'll let FileField handle that:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_content_is_empty( $item, $field ) {
return filefield_content_is_empty( $item, $field );
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In the second example, the person field is considered empty if there is no name entered:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_content_is_empty($item, $field) {
if (empty($item['displayed_name'])) {
return TRUE;
}
return FALSE;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;"></div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In our image/caption field we don't have a default value, actually (it isn't too common), but just in case FileField implements a default value setting in the future, we'll let FileField define the default value:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_default_value(&$form, &$form_state, $field, $delta) {
return filefield_default_value($form, $form_state, $field, $delta);
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Our person field doesn't have a default value either. If you want a default value for your field, you'll probably need to set something up in your settings form so that your users can define what the default value is, and then use the default value hook to set it up. I don't know of a good example for this.</div><hr style="background-color: #679046; border-bottom-color: rgb(103, 144, 70); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(103, 144, 70); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(103, 144, 70); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(103, 144, 70); border-top-style: solid; border-top-width: 1px; color: #679046; height: 4px;" /><a href="http://www.blogger.com/post-edit.g?blogID=1832814905954873603&postID=5689735434114544595" name="widget"></a><br />
<h2 style="font-size: medium; font-weight: bold; line-height: 1.3em; margin-bottom: 0.667em; margin-top: 0.667em;">Defining the Widget</h2><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Now that we have the CCK field itself defined, our next task is to define a "widget", which is the CCK name for a form used to edit the field.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For the first example, our widget will need to provide a way to upload the image file and preview/change the uploaded file; enter the alt, title, and caption text; choose an input format for the caption; and choose a taxonomy term (we'll use a drop-down select list for that). As before, we'll let FileField and Content Taxonomy handle their parts, so all we'll need to do is add the text fields and image format. We'll create a widget called "Image, Caption, Taxonomy Select", with machine-readable name "img_cap_tax_sel_widget", referred to below as "(widget)".</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For the second example, our person widget will just need to let us enter text for the name, position, phone, and email address. We'll define a widget with a human-readable label of "Text fields", and machine-readable name "person_entry", referred to below as "(widget)".</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">I will note here that it is possible for a CCK field module to define more than one widget for a single field. For instance, the Content Taxonomy module has several options: a drop-down select list, a type-ahead auto-complete text field, etc. There are notes below on what you'd need to change to add additional widgets.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_widget_info()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The first step in providing a widget is to give CCK the basic widget information (machine-readable name, human-readable name, what field types it applies to, etc.), by implementing the CCK hook_widget_info():</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_widget_info() {
return array(
'img_cap_tax_sel_widget' => array(
'label' => t('Image, Caption, Taxonomy Select'),
'field types' => array('img_cap_tax'),
'multiple values' => CONTENT_HANDLE_CORE,
'callbacks' => array('default value' => CONTENT_CALLBACK_CUSTOM),
'description' => t('An edit widget for Image Caption Taxonomy fields that allows upload/preview of the image, and chooses taxonomy terms from a drop-down select list.' ),
),
);
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">As is common in Drupal, the return value of this hook is an associative array of associative arrays, and if we wanted to provide multiple widgets in our module, we would just need to add additional elements to the outer array.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The person example is similar:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_widget_info() {
return array(
'person_entry' => array(
'label' => t('Text fields'),
'field types' => array('person'),
'multiple values' => CONTENT_HANDLE_CORE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
</pre><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">FAPI hook_elements()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Next, we need to define the widget's data entry form and how to process it. This is done using the core Forms API hook_elements(), which returns an associative array with one element (or more, if you have multiple widgets) whose key is the machine-readable name of our widget, and whose value is an associative array that either defines the form completely (as is done in the Content Taxonomy module), or gives a "process" callback function and some other information (as is done in ImageField; this is also the method recommended, in general, for the Forms API). We'll use the process callback method, and in the first example, let ImageField and FileField set up most of the array:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_elements() {
$imgel = imagefield_elements();
$elements = array( 'img_cap_tax_sel_widget' => $imgel[ 'imagefield_widget' ]);
$elements['img_cap_tax_sel_widget']['#process'][] = 'img_cap_tax_fld_widget_process';
$elements['img_cap_tax_sel_widget']['#element_validate']= array('img_cap_tax_fld_widget_validate');
return $elements;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Here's the second example, which is even simpler:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_elements() {
$elements = array( 'person_entry' =>
array(
'#input' => TRUE,
'#process' => array( 'person_fld_person_entry_process' ),
),
);
return $elements;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">We will need to define the "process" callback functions for both examples, which is what actually defines the form elements -- see section below. Also, for the image example we have a custom validate callback, because the one used by FileField (and ImageField) does not work for our module -- see section below. One other detail is that we'll also need to register a themeable element for this widget form; we'll cover that in the "Formatter and Theming" section below with the other theme information, and show the theming functions below.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">Process and Validate Callbacks for Widget Form</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The "process" callbacks from the form array of the previous section are what actually define and return the form elements (a Forms API array). In the first example, we've left ImageField to take care of its processing, and added our processing function to the end; we'll put the function in file (module)_widget.inc. So, our function needs to add a text area and input format selector for the "caption" field and a drop-down list for the Taxonomy term. All of this information will get stored in FileField's "data" array, and we'll have to be careful to choose the same array keys as the Content Taxonomy module for the taxonomy fields. For the caption's input format, we want to choose "format" as the array key, because this is the standard field name for input formats. (Some other modules depend on that convention; for example, the WYSIWYG editor module chooses which fields to attach editors to by looking for textarea fields that are followed by "format" fields.)</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_sel_widget_process($element, $edit, &$form_state, $form) {
$defaults = $element['#value']['data'];
if( !is_array( $defaults )) {
$defaults = unserialize( $defaults );
}
$field = content_fields($element['#field_name'], $element['#type_name']);
$element['data']['caption'] = array(
'#title' => t( 'Caption' ),
'#type' => 'textarea',
'#rows' => $field['widget']['rows'],
'#cols' => $field['widget']['cols'],
'#default_value' => $defaults['caption'],
'#weight' => 4,
);
if (!empty($field['text_processing'])) {
$filt = isset( $defaults['format'] ) ? $defaults['format'] : FILTER_FORMAT_DEFAULT;
$par = $element['#parents'];
$par[] = 'data';
$par[] = 'format';
$element['data']['format'] = filter_form( $filt, 1, $par );
$element['data']['format']['#weight'] = 5;
}
$mult = $field['allow_multiple'];
$req = $field['required_term'];
$opts = content_taxonomy_allowed_values( $field );
if( !$req && !$mult ) {
$none = theme( 'content_taxonomy_options_widgets_none', $field );
$opts = array( '' => $none ) + $opts;
}
$element['data']['value'] = array(
'#title' => t( 'Taxonomy Terms' ),
'#type' => 'select',
'#default_value' => $defaults['value'],
'#options' => $opts,
'#weight' => 6,
);
if( $mult ) {
$element['data']['value']['#multiple'] = TRUE;
}
return $element;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Note that the rows and columns settings for the caption, as well the settings for whether the taxonomy term is a single or multiple select and required or not, come from the widget settings form -- see CCK hook_widget_settings() below.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In the second example, we just need to define the text fields for entering person information:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_person_entry_process($element, $edit, &$form_state, $form) {
$defaults = $element['#value'];
$field = content_fields($element['#field_name'], $element['#type_name']);
$element['displayed_name'] = array(
'#title' => t( 'Name' ),
'#type' => 'textfield',
'#default_value' => $defaults['displayed_name'],
'#weight' => 2,
);
$element['job_title'] = array(
'#title' => t( 'Job Title' ),
'#type' => 'textfield',
'#default_value' => $defaults['job_title'],
'#weight' => 3,
);
$element['phone'] = array(
'#title' => t( 'Phone' ),
'#type' => 'textfield',
'#default_value' => $defaults['phone'],
'#weight' => 4,
);
$element['email'] = array(
'#title' => t( 'Email' ),
'#type' => 'textfield',
'#default_value' => $defaults['email'],
'#weight' => 5,
);
return $element;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The first example module also needs a validation callback, which will verify information when the node edit form is submitted. In FileField, the validation checks to make sure the file exists, and that if the field can only reference a file if it has been uploaded via this field module (so that the field will not be deleted erroneously if the node is deleted). Unfortunately, the existing FileField validate function (filefield_widget_validate() in filefield_widget.inc) will not work as-is for our module, because it tacitly assumes that the field type name is 'filefield', which is not the case for our field. So, we have to create our own function to replicate it. Assuming that the person using this field is uploading their own images and not doing anything crazy, all we really need to do is make sure the file exists. Here's the function:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_widget_validate(&$element, &$form_state) {
if (empty($element['fid']['#value'])) {
return;
}
$field = content_fields($element['#field_name'], $element['#type_name']);
$ftitle = $field['widget']['label'];
if ( !( $file = field_file_load($element['fid']['#value']))) {
form_error($element, t('The file referenced by the %field field does not exist.', array('%field' => $ftitle )));
}
}
</pre><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">Widget theme function</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">In order to display the editing widget, we need to define a theme function, theme_(widget), which is called as an envelope for each item when it is added to the node editing form. This function is simple for both cases: we just tell Drupal to render the form, and our processing functions will take care of the rest. Here are the functions for the two examples:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function theme_img_cap_tax_sel_widget(&$element) {
return theme('form_element', $element, $element['#children']);
}
function theme_person_entry($element) {
return $element['#children'];
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Note that there appears to be a rather annoying choice in the FileField CSS file that makes the editing widget get very narrow. You may want to add this to your theme's CSS file:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">.filefield-element .widget-edit, .filefield-element .widget-preview {
float: none;
}
</pre><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_widget()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The next hook we need to implement in order to define the editing widget is CCK hook_widget(). This hook will be called each time one of our fields is added to the form, with the $delta parameter set to the multiple-value index (0 for the first item, 1 for the second, etc.). The return value is a Forms API array that should set up default values for the form and define callbacks. In the first example, as usual, we'll let FileField and ImageField handle most of the details (Content Taxonomy doesn't need to do anything special), by calling the filefield_widget() function. That function assumes that:</div><ul style="list-style-type: disc; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; padding-left: 2em;"><li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">Our module contains a file called (module)_widget.inc (the filefield_widget() function will load it).</li>
<li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">The $items['delta'] array has been set up with an array of the default values for the text fields in our compound field, before filefield_widget() is called.</li>
</ul><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">So, our hook_widget() implementation is:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_widget(&$form, &$form_state, $field, $items, $delta = 0) {
if (empty($items[$delta])) {
$items[$delta] = array('alt' => '', 'title' => '', 'caption' => '', 'value' => 0);
}
$element = filefield_widget($form, $form_state, $field, $items, $delta);
$element['#upload_validators'] += imagefield_widget_upload_validators($field);
return $element;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The person field example's hook_widget() is even simpler, since all it has to do is tell CCK to load the field type we've already defined:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function person_fld_widget(&$form, &$form_state, $field, $items, $delta = 0) {
$element = array(
'#type' => $field['widget']['type'],
'#default_value' => isset($items[$delta]) ? $items[$delta] : '',
);
return $element;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;"></div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">If your module contains more than one widget, you'll want to do something like this in your hook_widget() implementation:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">switch( $field['widget']['type'] ) {
case 'first_widget_machine_name':
(code for this widget)
break;
case 'second_widget_machine_name':
(code for this widget)
break;
}
</pre><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_widget_settings() (image field only)</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">The final piece in defining the widget is to create a widget settings form, which is done by implementing CCK hook_widget_settings(). Like many of the other CCK hooks, hook_widget_settings() has several operations: one to create a settings form, one to validate the form, and one to save the form. Our second example has no settings for the widget, so we don't need to implement this hook. For the first example, we'll let ImageField take care of validation, and build our own functions for the form and save operations:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_widget_settings( $op, $widget ) {
switch ($op) {
case 'form':
return img_cap_tax_fld_widget_settings_form($widget);
case 'validate':
return imagefield_widget_settings_validate($widget);
case 'save':
return img_cap_tax_fld_widget_settings_save($widget);
}
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;"></div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Note that if you have multiple widgets in your module, you can do a switch on $widget['type'] to handle the different widgets in your hook_widget_settings() implementation.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">filefield_widget_settings() callbacks (image field only)</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">There are two operation callbacks defined in our hook_widget_settings() implementation for the image field example. The 'form' operation returns the widget settings form; the 'save' operation returns a list of which form data should be saved to the database.</div><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">First, let's work on the settings form. The existing FileField and ImageField modules have a widget settings form that lets the user set a file path, allowed file extensions, maximum file size, and other settings. We'll use that form, but modify it so that alt and title can always be customized rather than leaving those as options as they are in ImageField (we still want the settings to be there, so that other ImageField functions we call will have the right values set). The Content Taxonomy select list widget has settings for indentation and grouping terms, which we'll also want. Finally, most multi-line text fields let the user choose how many rows and/or columns to display, so we'll want that setting for the caption field. Putting this all together:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_widget_settings_form( $widget ) {
$form = imagefield_widget_settings_form( $widget );
$form['custom_alt'] = $form['alt_settings']['custom_alt'];
$form['custom_alt']['#type'] = 'hidden';
$form['custom_alt']['#value'] = 1;
$form['alt'] = $form['alt_settings']['alt'];
$form['alt']['#type'] = 'hidden';
$form['alt']['#value'] = '';
unset( $form['alt']['#suffix'] );
unset( $form['alt_settings'] );
$form['custom_title'] = $form['title_settings']['custom_title'];
$form['custom_title']['#type'] = 'hidden';
$form['custom_title']['#value'] = 1;
$form['title'] = $form['title_settings']['title'];
$form['title']['#type'] = 'hidden';
$form['title']['#value'] = '';
unset( $form['title']['#suffix'] );
unset( $form['title_settings'] );
$rows = (isset($widget['rows']) && is_numeric($widget['rows'])) ? $widget['rows'] : 5;
$form['rows'] = array(
'#type' => 'textfield',
'#title' => t('Number of rows in caption field'),
'#default_value' => $rows,
'#element_validate' => array('_text_widget_settings_row_validate'),
'#required' => TRUE,
'#weight' => 8,
);
$cols = (isset($widget['cols']) && is_numeric($widget['cols'])) ? $widget['cols'] : 40;
$form['cols'] = array(
'#type' => 'textfield',
'#title' => t('Number of columns in caption field'),
'#default_value' => $cols,
'#element_validate' => array('_text_widget_settings_row_validate'),
'#required' => TRUE,
'#weight' => 9,
);
$form2 = content_taxonomy_options_widget_settings( 'form', $widget );
$form2['settings']['#title'] = t( 'Settings for Taxonomy' );
$form = $form + $form2;
return $form;
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">We don't need to do anything special for the 'validate' operation, as neither ImageField nor Content Taxonomy needs us to do anything beyond what FileField does. So, we won't define this function. The 'save' operation returns a list of fields to save from the settings form:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_widget_settings_save( $widget ) {
$arr = imagefield_widget_settings_save( $widget );
$arr[] = 'rows';
$arr[] = 'cols';
$arr2 = content_taxonomy_options_widget_settings( 'save', $widget );
$arr2[] = 'allow_multiple';
$arr2[] = 'required_term';
return array_merge( $arr, $arr2 );
}</pre><hr style="background-color: #679046; border-bottom-color: rgb(103, 144, 70); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(103, 144, 70); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(103, 144, 70); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(103, 144, 70); border-top-style: solid; border-top-width: 1px; color: #679046; height: 4px;" /><a href="http://www.blogger.com/post-edit.g?blogID=1832814905954873603&postID=5689735434114544595" name="formatter"></a><br />
<h2 style="font-size: medium; font-weight: bold; line-height: 1.3em; margin-bottom: 0.667em; margin-top: 0.667em;">Defining the Formatter and Theming</h2><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Having now defined our field and the editing widget, the final thing we need to do is to define how it will look to someone who is visiting the site (of course, the theme can override this). We do this by defining a "formatter" for the field; like widgets, there can be more than one formatter defined for a field, but we'll only create one in this example. We'll give our formatter the machine name 'default', which we'll refer to as "(formatter)" below, and human-readable name 'Image with Caption and Taxonomy Terms' for the first example, and 'Person display' in the second example. Note that machine-readable names for formatters do not need to be unique, except within your module.</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">CCK hook_field_formatter_info()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">To tell CCK about our formatter, we implement CCK hook_field_formatter_info():</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_field_formatter_info() {
return array(
'default' => array(
'label' => t( 'Image with Caption and Taxonomy Terms' ),
'field types' => array( 'img_cap_tax' ),
),
);
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">(This is nearly identical for the person field example.)</div><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">Core hook_theme()</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Once the formatter has been defined, CCK will assume there is a corresponding themeable element called (module)_formatter_(formatter), which we need to register in the core hook_theme(). As noted above, we also need to register the themeable element for the widget form, so our hook_theme() implementation for the first example is (the second is quite similar):</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function img_cap_tax_fld_theme() {
return array(
'img_cap_tax_sel_widget' => array(
'arguments' => array('element' => NULL),
),
'img_cap_tax_fld_formatter_default' => array(
'arguments' => array('element' => NULL),
),
);
}
</pre><h3 style="font-size: small; font-style: italic; font-weight: bold; line-height: 1.3em; margin-bottom: 0.769em; margin-top: 0.769em;">Theme Functions</h3><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">Finally, we need to create a theme_(element) function for the formatter (the widget theme functions were given in previous sections). For the first example, the formatter theme function displays the image, caption, and taxonomy term:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function theme_img_cap_tax_fld_formatter_default( $element = NULL ) {
if( empty( $element['#item'] )) {
return '';
}
$img = theme( 'imagefield_formatter_image_plain', $element );
$cap = $element['#item']['safe_caption'];
$tax = '';
$sep = '';
$val = $element['#item']['data']['value'];
if( !is_array( $val )) {
$val = array( $val );
}
foreach( $val as $tid ) {
$term = taxonomy_get_term( $tid );
$tax .= $sep . check_plain( $term->name );
$sep = ', ';
}
return '<div class="imgcaptax_outer">' .
'
<div class="imgcaptax_img">' . $img . '</div>' .
'
<div class="imgcaptax_cap">' . $cap . '</div>' .
'
<div class="imgcaptax_tax">' . $tax . '</div>' .
'</div>';
}
</pre><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">For the second example:</div><pre style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 0.8em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">function theme_person_fld_formatter_default($element = NULL) {
if(empty($element['#item'])) {
return '';
}
$stuff = $element['#item'];
$flds = array('displayed_name', 'job_title', 'phone');
$ret = '<div class="staff_info">';
$sep = '';
foreach($flds as $fld) {
if(!empty($stuff['safe_' . $fld ])) {
$ret .= $sep . '<span class="' . $fld . '">' . $stuff['safe_' . $fld ] . '</span>';
$sep = "
\n";
}
}
if(!empty($stuff['safe_email' ])) {
$ret .= $sep . '<a class="staff_email" href="mailto:' . $stuff['safe_email' ] . '">' . $stuff['safe_email' ] . "</a>";
}
$ret .= '</div>';
return $ret;
}</pre><hr style="background-color: #679046; border-bottom-color: rgb(103, 144, 70); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(103, 144, 70); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(103, 144, 70); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(103, 144, 70); border-top-style: solid; border-top-width: 1px; color: #679046; height: 4px;" /><a href="http://www.blogger.com/post-edit.g?blogID=1832814905954873603&postID=5689735434114544595" name="details"></a><br />
<h2 style="font-size: medium; font-weight: bold; line-height: 1.3em; margin-bottom: 0.667em; margin-top: 0.667em;">Final Details</h2><div style="margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em;">One further detail... If you are using the "private" file download method on your Drupal site (in the Site Configuration section of administration, under File System), you will find that the Image Caption Taxonomy field doesn't work unless you implement hook_file_download(). The reason for this is that when you use the private file download method, the system asks each module to verify that a given file can be downloaded, before allowing someone access to that file. So, our field module needs to tell the system which files it contains, to allow them to be downloaded. This function is included in the sample module.</div></div>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-35556046059558414492011-03-08T21:14:00.000-08:002011-03-08T21:14:22.988-08:00FB.login() called before calling FB.init(). Drupal<div dir="ltr" style="text-align: left;" trbidi="on">If you are a drupal developer using FBConnect and FB Social and in some situation you get an error like '<b>FB.login() called before calling FB.init().</b>' then the first thing you need to check is that APPID is available on the settings page of both modules. <br />
<br />
I got it fixed in this way today.</div>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-44782754641348664172010-12-31T05:26:00.001-08:002010-12-31T05:26:45.298-08:00Rework by 37SignalsDownload here.<br />
<br />
<a href="http://uploading.com/files/657885dm/Fried%252C%2BJason%2B-%2BRework.rar/">Fried, Jason - Rework.rar - 11.2 MB</a>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-80793745012640752432010-05-23T20:16:00.000-07:002010-09-27T23:11:03.989-07:00Code Jam Round 1<a href="http://code.google.com/codejam">Code Jam’s</a> Round 1 is over now and I didn’t make it to the next round as last year :-(. I am pretty sad and writing this entry with heavy heart but on the other hand quite satisfied by my performance as I was eliminated with very close competition. Let me describe you my sad story.<br />
<br />
Round 1 consisted of <a href="http://code.google.com/codejam/rules.html#how_to_advance_to_the_finals">3 sub rounds</a> of 2hr 30min duration each and top 1000 finishers from each round were to qualify to Round 2.<br />
<br />
Round 1A was at <a href="http://code.google.com/codejam/schedule.html">6:00 AM, Saturday, May 22, 2010</a>. I was in my friend’s home on that day. I woke up early with great enthusiasm after a 4 hours nap and started the computer. The development environment is not set on that system. “Its ok, no problem, lets setup the development environment”. It penalized me about 15 minutes. Started solving the first problem, applied brute force and it was accepted but I took 1hr 15min to solve it. Now I was just looking for one more solution for small input for a finish under top 1000. Started the second problem, solved it, submitted it and “Aah! INCORRECT RESULT”. I made another attempt and same result again. Round over and I ranked about 1360 with 23 points. After system tests, I managed to finish at <a href="http://code.google.com/codejam/contest/scoreboard?c=544101#sp=1261">1269</a>. I was pretty happy with my performance as I was very close for getting through. The person at 1000th place was also with the same score but with less time penalty i.e. <a href="http://code.google.com/codejam/contest/scoreboard?c=544101#sp=981">51min 40sec</a>.<br />
<br />
Round 1B was at 9:00 PM on the same day. O boy, power cutoff from 8:00 PM – 10:00 PM, but I will participate from 10:00 PM onwards. At 10:00 PM, I entered in to the contest. 1 hour is already spent in load shedding so I have to be fast and accurate. I started Problem A, solved it in almost 43 minutes and it got accepted. Problem B was also easy, just a bubble sort algorithm. I got it accepted in almost 35 minutes with one wrong try. I finished at 56 points with total time <a href="http://code.google.com/codejam/contest/scoreboard?c=635101#sp=1361">2hr 26min 06sec</a> (1hr 26min 06sec of contest + 1 hr of load shedding). Ranked 1410 and after System Tests <a href="http://code.google.com/codejam/contest/scoreboard?c=635101#sp=1341">1352</a>. The interesting part is that the person ranked 1000 spent 1hr 26min 15sec so I am qualified if I subtract 1 hour of load shedding. :-)<br />
<br />
Round 1C was at 2:00 PM, Sunday, May 23, 2010. Load shedding from 2:00 - 4:00. No chance. So this is how I <a href="http://www.go-hero.net/jam/10/name/qasim">eliminated</a> :-(.<br />
<br />
<b>Lessons Learned:</b><br />
1.<span class="Apple-tab-span" style="white-space: pre;"> </span>Most importantly, I need more practice as in Round 1A, I got complete time but was just making a stupid mistake in 2nd problem.<br />
2.<span class="Apple-tab-span" style="white-space: pre;"> </span>Make sure the development environment is setup and working before contest.<br />
3.<span class="Apple-tab-span" style="white-space: pre;"> </span>Take at least 8 hours sleep before any programming contest.<br />
4.<span class="Apple-tab-span" style="white-space: pre;"> </span>If above rules are being obeyed, no one can stop you from being qualified to Round 2 even a power cut off.<br />
<br />
<b>Country Statistics:</b><br />
<a href="http://www.go-hero.net/jam/10/regions">Click here</a> to see the results of all countries.Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com4tag:blogger.com,1999:blog-1832814905954873603.post-68869351709361511782010-05-04T03:21:00.000-07:002010-05-07T03:16:01.692-07:00Clean Code by Rober C. Martin (Uncle Bob)<div class="MsoNormal">Thanks to <a href="http://twitter.com/jongman">JongMan Koo</a> for sharing this beautiful book. Frankly, I don’t like reading e-books but this book is really appealing and I am enjoying reading it. Most of the content of the book forced me to practice rather than just reading. Robert C. Martin has some great books related to principles of software design and patterns in his account. In this book he mainly forces on practicing the techniques of writing good code. He wrote:</div><div class="MsoNormal"><o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><span style="color: #231f20; font-family: TimesNewRomanPS; font-size: 10pt;"><i>“I can teach you the physics of riding a bicycle. Indeed, the classical mathematics is relatively straightforward. Gravity, friction, angular momentum, center of mass, and so forth, can be demonstrated with less than a page full of equations. Given those formulae I could prove to you that bicycle riding is practical and give you all the knowledge you needed to make it work. And you’d still fall down the first time you climbed on that bike.”<o:p></o:p></i></span></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">The tone of the writer is strident most of the time in this book. The style is a bit strict that attracts you a lot and you feel an emotional attachment with every word you read. He also explains how the bigger products are buried just because of nothing but bad code. He forces the reader not to write too much cluttering comments as it is difficult to maintain them with frequent changes, instead make your code self explainable. The naming conventions are beautifully explained. One sentence is constantly ticking me in this regard:<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><span style="color: #231f20; font-family: TimesNewRomanPS; font-size: 10pt;"><i>“You should name a variable using the same care with which you name a first-born child.”</i><o:p></o:p></span></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">“Uncle Bob” mainly explains what are the main components of a clean code in the light of various quotations made by some great scholars and practitioners in the history of computers. I haven’t read the complete book yet so I will not be able to summarize all the aspects the author covered but I assure you that some initial reading will definitely made you think about common mistakes we normally make. It is not just a theoretical book, it is for practitioners so a lot of real time examples are given in the final chapters to improve readers' capability of understanding bad practices and adapting better ones. <o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">If you are a coder with around 1 year of experience and you have seen a couple of ups and downs in your project, this book is highly recommended.<o:p></o:p></div>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-35868646439098648922010-04-15T05:24:00.000-07:002010-05-04T22:08:44.823-07:00Implementation of Full Text Search using MySQL database<div class="MsoNormal"><br />
“Search? Aha…lets use wildcard for now”. <o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">This is a very common phrase that appears when any site based on MySQL database requires “search” feature. Today, I read about another method of full text search that is not only faster but just took 10 minutes to be implemented. <o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Let say you are using something like:<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">SELECT * FROM blog WHERE body like ‘%full text query%’ OR title like ‘%full text query%’<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Above query may take a few milliseconds to execute but if you are required to join this table with other tables. Huh! Hell tough. And you are just fed up by adding too many indices on the columns but in vain. What to do? Here are some simple steps as alternative.<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><b>Step 1.</b> Create a FULLTEXT index :<o:p></o:p></div><div class="MsoNormal">ALTER TABLE blog ADD FULLTEXT(title, body)<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><b>Step 2.</b> Replace the above query with this one<o:p></o:p></div><div class="MsoNormal">SELECT * FROM blog WHERE MATCH(title, body) AGAINST (' full text query')<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Just make sure that whatever you are passing to MATCH() is passed to FULLTEXT() in Step 1.<o:p></o:p></div><div class="MsoNormal"><br />
</div><b>Step 3.</b> There is not step 3 :P, you are done.<br />
<div class="MsoNormal"><o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal">Advantages:<o:p></o:p></div><div class="MsoListParagraph" style="mso-list: l0 level1 lfo1; text-indent: -.25in;">1.<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span>Almost 10 times faster<o:p></o:p></div><div class="MsoListParagraph" style="mso-list: l0 level1 lfo1; text-indent: -.25in;">2.<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span>Results are sorted by relevance<o:p></o:p></div><div class="MsoListParagraph" style="mso-list: l0 level1 lfo1; text-indent: -.25in;">3.<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span>Each word of query string is matched.<o:p></o:p></div><div class="MsoNormal"><br />
</div><div class="MsoNormal"><br />
</div><div class="MsoNormal">References:<o:p></o:p></div><div class="MsoNormal"><a href="http://www.petefreitag.com/item/477.cfm">http://www.petefreitag.com/item/477.cfm</a><o:p></o:p></div><div class="MsoNormal"><a href="http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html">http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html</a><o:p></o:p></div><div class="MsoNormal"><br />
</div>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com4tag:blogger.com,1999:blog-1832814905954873603.post-11515395452749156552009-12-13T22:23:00.000-08:002009-12-15T09:58:45.996-08:00More than 31 Style elements cause IE crashLast week, I was trying to add Twitter Widget on my Webpage, it was working fine in Firefox, Chrome and Safari but in all versions of IE, it was causing crash :O<br />
<br />
"Oh IE I love, I can write an HTML file that can crash you"<br />
<br />
After figuring out the JavaScript of that twitter widget and some Google work, I got to know that the basic cause of IE crash is not the Twitter widget. The basic cause was that twitter widget adds a "style" HTML element dynamically, that causes crash for IE.<br />
<br />
I just squeeze all those 31 imports in one "<style> </style>" and hurray!!!! the problem is resolved.<br />
<br />
Reference: <a href="http://support.microsoft.com/kb/262161">Microsoft Support about 31 style tags</a>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com3tag:blogger.com,1999:blog-1832814905954873603.post-55332046581771590762009-10-29T10:38:00.000-07:002009-11-26T03:55:45.263-08:00Finding 100 factorial<b>Problem Statement: </b><br />
Write a program that takes input between 1 and 100 and finds its factorial.<br />
<br />
<b>Solution</b><br />
Often students find this problem as assignment or algorithm exercise. Some of them even get fed up and skip this problem because you have to make calculations on large numbers. We all know that C++ 32 bit unsigned integer can hold data up to 4294967295 and long long i.e. 64 bit integer can handle at max 2<sup>64</SUP> - 1 = 18446744073709551615. What do you think what is the maximum value whose factorial can be saved in 64 bit int. You can't even store 25's factorial in it as 25! = 15511210043330985984000000 :)<br />
<br />
In this post, I will explain how easy it is to actually implement this algorithm. In the second part of this post, we will optimize our algorithm and will reduce some calculations.<br />
<br />
Let us start!<br />
<br />
First thing we have to keep in mind that we actually need a function that has the capability to multiply fairly large numbers.<br />
<br />
We multiply two numbers usually by multiplying each digit of first number with each digit of 2nd number. For example if I have to multiply 123 to 1234: <br />
<ol><li> I will actually find 3 x 1234 = 3702, 2 x 1234 = 2468 and 1 x 1234 = 1234. <br />
<li> I also have to add some zeros on the right side as I move from right to left. <br />
<li> And then I will add all these values i.e. 3702 + 2468<b>0</b> + 1234<b>00</b> = 151782.<br />
</OL><p>Voila!!! you noted something, we have to implement another function that can add two large numbers. Don't worry, it is good that we have found it initially. Let us assume that we already have a function that can add two numbers 'string add(string str1, string str2)' Now the function <b>mul</b> is quite simple to write that will multiply two very large numbers.</p><pre style="font-size: 150%; color: maroon; font-weight: bold">string mul(string str1, string str2)
{
string ans;
for(int i = str1.size()-1; i>=0; i--)
{
string sum;
int carry = 0;
//Step 1. above
for(int j = str2.size()-1; j >=0; j--)
{
//multiply two digits and add carry
int k = ((str1[i]-'0')*(str2[j]-'0') + carry);
sum = (char)((k % 10) + '0') + sum;
carry = (k/10);
}
if(carry > 0)
{
sum = (char)(carry+'0') + sum;
}
//Step 2. above
for(int j = 0; j < str1.size() - 1 - i; j++)
{
sum+="0";
}
//Step 3. above
ans = add(ans, sum);
}
return ans;
}
</PRE>
And here we go with the add function, I think it is pretty simple to understand
<pre style="font-size: 150%; color: maroon; font-weight: bold">string add(string str1, string str2)
{
int n1 = str1.size(), n2 = str2.size();
for(int i = 0; i < n1 - n2; i++) //Make 134 as 00134 if 2nd number is 12345
str2 = "0" + str2;
for(int i = 0; i < n2 - n1; i++)
str1 = "0" + str1;
string ans;
int carry = 0;
for(int i = str1.size() - 1; i >= 0; i--)
{
ans = (char)((str1[i] - '0' + str2[i] - '0' + carry) % 10 + '0') + ans;
carry = (str1[i] - '0' + str2[i] - '0' + carry)/10;
}
if(carry > 0)
ans = (char)(carry + '0') + ans;
return ans;
}
</PRE>Now what is more difficult for you. Here comes the Factorial function:
<pre style="font-size: 150%; color: maroon; font-weight: bold">int N = 25; //We need 25!
string ans = 1;
for(j = 1; j <= N; j++)
{
stringstream ss;
ss << j;
ans = mul(ss.str(),ans);
}
</PRE>
<b>Optimization</b>
Just check one important thing, even we have to multiply small numbers. we have to make large calculations.
For example, if I want to multiply 10000 to 9999. I have to make 20 calculations but it is possible in just 1 calculation and the result can also be saved in an integer so we can optimize our algorithm in this way.
We will not call <b>mul( )</b> function, until and unless it exceeds the limit of an integer that is '2147483647' and then multiply it with the next number.
25! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 x 13 x 14 x 15 x 16 x 17 x 18 x 19 x 20 x 21 x 22 x 23 x 24 x 25
Now we can find product upto 12 i.e. '479001600' and from 13 to 19 i.e. '253955520' and then call <b>mul( )</b> function on these two strings.<br />
<br />
I am sure, it will save a lot of calculations.Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com5tag:blogger.com,1999:blog-1832814905954873603.post-59659972781555684042009-10-12T20:40:00.000-07:002009-10-12T20:40:18.239-07:00Lecture about dynamic programming (Urdu)Hi all,<br />
<br />
While searching educational stuff on youtube, I found these videos those I would like to share with you.<br />
<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/l9yoeDA1n0c&hl=en&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/l9yoeDA1n0c&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object><br />
<br />
and the next part is:<br />
<br />
<object width="384" height="313"><param name="movie" value="http://www.youtube.com/v/wfptwGZ8Wzo&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/wfptwGZ8Wzo&hl=en&fs=1" type="application/x-shockwave-flash" width="384" height="313" allowscriptaccess="always" allowfullscreen="true"></embed></object>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-57985712411515507062009-09-26T20:44:00.000-07:002009-09-26T20:44:07.638-07:00Topcoder | SRM 449 experienceThis time the performance was a bit disappointing. The problems were related to mathematics and trigonometry.<br />
<br />
I spent some time on <a href="http://www.topcoder.com/stat?c=problem_statement&pm=10546&rd=13903">250 ptr</a> and just didn't understand that if I scale its lower parts to upward, it will become a bigger triangle, and I just have to find the lengths of base and perpendicular of that bigger triangle. The formula was sqrt(2)*(max(finish) - min(start)). This is the <a href="http://www.topcoder.com/stat?c=problem_solution&rm=302328&rd=13903&pm=10546&cr=22827157">solution</a>.<br />
<br />
Just no idea clicked and I decided to open <a href="http://www.topcoder.com/stat?c=problem_statement&pm=10547&rd=13903">500 ptr</a> because I was pretty sure that it would have been a simpler one. It was simple(only problem statement :) ), as you might have seen but wasn't easy. Again it was a mathematical trick, because brute force solution will surely leads to time out. This was the logic behind it. (The following statements are copied from <a href="http://www.topcoder.com/wiki/display/tc/SRM+449">editorial</a>)<br />
<br />
<i>-> If we see, the greatest odd divisor that divides N is N if N is odd or if N is even the greatest odd divisor of N is F(N/2).<br />
-> For (1,N) if N is odd we get 1 + 3 + 5 + ...N + F(2) + F(4)+....F(N-1). The greatest even N is F((N-1)/2).<br />
-> That means the sum F(2) + F(4)+...F(N-1) = F(1) + F(2) + F(3) + F((N-1)/2). Now this is our original problem with N as (N-1)/2.<br />
-> In case of N as even our problem is split into 1+3+5+ ....N-1 and F(2)+ F(4) + ......+ F(N), which is again sum(1,N/2).<br />
-> Now the sum of 1+3+5+.....+N= (N+1)*(N+1)/2</i><br />
<br />
Click here for its <a href="http://www.topcoder.com/stat?c=problem_solution&rm=302328&rd=13903&pm=10547&cr=22827157">solution.</a> <br />
<br />
After a sad Coding phase, I decided to gain some points in challenge phase, I was sure that many participants will attempt <a href="http://www.topcoder.com/stat?c=problem_statement&pm=10547&rd=13903&rm=302328&cr=22827157">500 ptr</a> as brute force so I attacked them, I made 3 challenges one of them was wrong and finished at 75. <br />
<br />
Next day, I opened the page to see how much rating points I lost, I was amazed that these were not too many.Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0tag:blogger.com,1999:blog-1832814905954873603.post-85434196925252687362009-09-04T17:37:00.000-07:002009-09-04T18:13:35.024-07:00Google Code JAMGoogle Code JAM Qualification round is over. Unfortunately, code JAM's <a href="http://code.google.com/codejam/contest/scoreboard?c=90101#">scoreboard</a> doesn't give much statistics about the results<br />
<br />
I saw these stats about google code JAM and I would surely like them to share with all of my readers.<br />
<br />
<a href="http://www.go-hero.net/jam/09/languages">Language statistics</a><br />
<br />
<a href="http://www.go-hero.net/jam/09/solutions">Solutions by Language</a><br />
<br />
<a href = "http://www.go-hero.net/jam/09/regions">Regional Statistics</a><br />
<br />
Hope this will help.Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com1tag:blogger.com,1999:blog-1832814905954873603.post-46017086795788065352009-08-26T09:17:00.000-07:002009-08-27T05:58:32.576-07:00Topcoder | SRM 447 experience<html><br />
<head><br />
<meta name="verify-v1" content="e2ThjefBw8gqAefekwtYxr+IaodiUqpj0oeJlgPC0Mg=" ><br />
</head><br />
<meta equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><o:smarttagtype namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="country-region"></o:smarttagtype><o:smarttagtype namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="place"></o:smarttagtype><!--[if gte mso 9]><xml> <w:worddocument> <w:view>Normal</w:View> <w:zoom>0</w:Zoom> <w:punctuationkerning/> <w:validateagainstschemas/> <w:saveifxmlinvalid>false</w:SaveIfXMLInvalid> <w:ignoremixedcontent>false</w:IgnoreMixedContent> <w:alwaysshowplaceholdertext>false</w:AlwaysShowPlaceholderText> <w:compatibility> <w:breakwrappedtables/> <w:snaptogridincell/> <w:wraptextwithpunct/> <w:useasianbreakrules/> <w:dontgrowautofit/> </w:Compatibility> <w:browserlevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:latentstyles deflockedstate="false" latentstylecount="156"> </w:LatentStyles> </xml><![endif]--><!--[if !mso]><object classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id="ieooui"></object> <style> st1\:*{behavior:url(#ieooui) } </style> <![endif]--><style> <!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} a:link, span.MsoHyperlink {color:blue; text-decoration:underline; text-underline:single;} a:visited, span.MsoHyperlinkFollowed {color:purple; text-decoration:underline; text-underline:single;} @page Section1 {size:8.5in 11.0in; margin:1.0in 1.25in 1.0in 1.25in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1745107820; mso-list-type:hybrid; mso-list-template-ids:-904131306 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l0:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} ol {margin-bottom:0in;} ul {margin-bottom:0in;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]--> <p class="MsoNormal">Hi all,</p><p class="MsoNormal"><br />
</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal">Again a very interesting experience.</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal">The most amazing thing was that the count of contestants from <st1:country-region st="on">Pakistan</st1:country-region> in this SRM was just ‘One’ and the reason was so obvious that it was at 7:00 AM and most of the contestants from <st1:country-region st="on"><st1:place st="on">Pakistan</st1:place></st1:country-region> would have been sleeping at that time after having Saheri :)</p><p class="MsoNormal"><br />
</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal">The SRM was special in this sense because it was sponsored by <b style="">facebook</b> and top 3 positions of a room in DIV I and top 2 positions in DIV II got the <a href="http://www.topcoder.com/tc?module=MatchDetails&rd=13901">prize money</a>.</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal"><br />
</p><p class="MsoNormal">This time, again, I managed to solve only two problems.</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal"><br />
</p><p class="MsoNormal">The first problem was a bit simple. See the <a href="http://www.topcoder.com/stat?c=problem_statement&pm=10578&rd=13901&rm=302145&cr=22020968">problem statement</a>:</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal">This simple problem took me 10 minutes to solve and the problem was lack of practice. There were two possible solutions for this problem:</p><p class="MsoNormal"><o:p> </o:p></p><ol style="margin-top: 0in;" start="1" type="1"><li class="MsoNormal" style="">Sort both arrays in descending order and get the first ever value from “<b>computers</b>” that is greater than or equal to the current value of “<b>complexity</b>”. It can be done in just one loop iteration. See the <a href="http://www.topcoder.com/stat?c=problem_solution&rm=302145&rd=13901&pm=10578&cr=22830867">code</a>.</li>
<li class="MsoNormal" style="">Don’t sort the array and just solve it using nested loop. This strategy was a dirty one and I did this :P. See the <a href="http://www.topcoder.com/stat?c=problem_solution&rm=302145&rd=13901&pm=10578&cr=22020968">code</a> </li>
</ol><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal"><br />
</p><p class="MsoNormal">The code for 500 pointer was a bit simple. Just do it as it is given in the <a href="http://www.topcoder.com/stat?c=problem_statement&pm=10577&rd=13901&rm=302145&cr=22830867">problem statement</a>. My code is here, let us see whether some better suggestions are there or not. Looking for comments</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal"><br />
</p><p class="MsoNormal">Oh! The code is <a href="http://www.topcoder.com/stat?c=problem_solution&rm=302145&rd=13901&pm=10577&cr=22830867">here</a>.</p><p class="MsoNormal"><o:p> </o:p></p><p class="MsoNormal"><br />
</p><p class="MsoNormal">In challenge phase I didn’t participated because I was 3<sup>rd</sup> after coding phase in my room and there was a chance that after System Tests, I would have been managed to go to 2<sup>nd</sup> and qualify for the prize money, so same thing happened Al-hamdulillah and I finished at 2<sup>nd</sup>.</p></html>Qasim Zeeshanhttp://www.blogger.com/profile/12935549823010205477noreply@blogger.com0