coding

You are currently browsing articles tagged coding.

Check your TC stats

jmzero’s website gives a comprehensive analysis of your past performance in topcoder competitions. It shows your weak areas and your strengths.

It also gives a comparison of your performance with contestants with similar ratings and with Petr. It shows you when you have outperformed Petr :-o .

Tags: ,

I found this awesome video in digg. Enjoy!

Tags: ,

Since it took me so long to find the wall of a huge messy profile of a friend when I wanted to say Happy Birthday, I was thinking of doing it by a simple HTTP POST.

First you need to gather following information

  1. Your post_form_id
  2. Your profile id
  3. Your friend’s profile id

That’s all you need, and you must be logged in to your facebook account (doesn’t matter if you have checked remember me).

Then type in the following html code and save it as a .htm file and double click on it. That’s it your message will be on your friends wall :) .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
 <body>
  <form id="fb_wall" name="fb_wall" method="post"
   action="http://www.facebook.com/wallpost.php?id=[YOUR FRIEND'S ID]">
 
   <input type="text" id="to" name="to" value="[YOUR FRIEND'S ID]" />
   <input type="text" id="wall_text" name="wall_text"
          value="Happy Birthday" />
   <input type="text" id="from" name="from" value="[YOUR ID]" />
 
   <input type="text" id="post_form_id" name="post_form_id"
          value="[YOUR post_form_id]" />
 
   <input type="submit" />
  </form>
  <script language="JavaScript">document.fb_wall.submit();</script>
 </body>
</html>

Ok, so how do we find the post_form_id and the two profile id’s. To find the post_form_id you need to go to your profile and click view source in the view menu of the browser then search for post_form_id.

Now the two ids; Go to your profile and your friend’s profile and you’ll find the id in the URL.

That’s it! Try it for yourself.

Tags: , , ,

This will not serve as a comprehensive tutorial in developing services and clients for Axis2/C, but rather intended to provide some help for starters.

Apache Axis2/C is an engine for web services developed in C – there’s another implementation in Java. You can find an illustration of SOA here.

You first need to download and install Apache Axis2/C 1.3.0. You can download the binaries or sources from the Apache Axis2/C website. It would be easier to install the binaries if you are a beginner.

So let’s get started with developing a service. We’ll create a service to sort a set of integers in ascending or descending order.

Service

The service should have two functions:

  • axis2_get_instant – creates the service skeleton
  • axis2_remove_instant – removes the instant

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
AXIS2_EXPORT int
  axis2_get_instance(axis2_svc_skeleton_t **inst,
                     const axutil_env_t *env)
{
 *inst = axis2_sort_create(env);
 if (!(*inst))
  return AXIS2_FAILURE;
 
 return AXIS2_SUCCESS;
}
 
AXIS2_EXPORT int
  axis2_remove_instance(axis2_svc_skeleton_t *inst,
                        const axutil_env_t *env)
{
 if (inst)
  return AXIS2_SVC_SKELETON_FREE(inst, env);
 
 return AXIS2_FAILURE;
}
 
/* Create the service skeleton */
axis2_svc_skeleton_t *
  axis2_sort_create(const axutil_env_t *env)
{
 axis2_svc_skeleton_t *svc_skeleton = NULL;
 svc_skeleton = AXIS2_MALLOC(env->allocator,
                             sizeof(axis2_svc_skeleton_t));
 
 svc_skeleton->ops = &sort_svc_skeleton_ops_var;
 
 svc_skeleton->func_array = NULL;
 
 return svc_skeleton;
}

axis2_get_instant should create axis2_svc_skeleton struct with corresponding functions assigned. These functions are

  1. init – initializes the skeleton
  2. invoke – invokes the service
  3. on_fault – this is called when an fault is detected
  4. free – frees the skeleton instant

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* Functions for axis2_svc_skeleton */
int AXIS2_CALL
  sort_free(axis2_svc_skeleton_t *svc_skeleton,
            const axutil_env_t *env);
 
axiom_node_t* AXIS2_CALL
  sort_invoke(axis2_svc_skeleton_t *svc_skeleton,
              const axutil_env_t *env,
              axiom_node_t *node,
              axis2_msg_ctx_t *msg_ctx);
 
int AXIS2_CALL
  sort_init(axis2_svc_skeleton_t *svc_skeleton,
            const axutil_env_t *env);
 
axiom_node_t* AXIS2_CALL
  sort_on_fault(axis2_svc_skeleton_t *svc_skeli,
                const axutil_env_t *env, axiom_node_t *node);
 
/* Skeleton */
static const axis2_svc_skeleton_ops_t sort_svc_skeleton_ops_var = {
 sort_init,
 sort_invoke,
 sort_on_fault,
 sort_free
};

Now comes the main part of the service – implementation of the invoke function.

This function will be called with a reference to request. The XML request will be passed as a axiom_node_t, and you can navigate through it easily using functions axiom_node_get_first_child and axiom_node_get_next_sibling.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* Process the request */
axiom_node_t* AXIS2_CALL
  sort_invoke(axis2_svc_skeleton_t *svc_skeleton,
               const axutil_env_t *env,
               axiom_node_t *node,
               axis2_msg_ctx_t *msg_ctx)
{
 return axis2_sort(env, node);
}
 
 /* Process the request */
axiom_node_t *
  axis2_sort(const axutil_env_t *env, axiom_node_t *node)
{
 AXIS2_ENV_CHECK(env, NULL);
 
 if(!node) return sort_error(env);
 
 axiom_node_t *order_node = axiom_node_get_first_child(node, env);
 axis2_char_t *order_str = get_string(order_node, env);
 
 if(!order_str) return sort_error(env);
 
 axiom_node_t *list = axiom_node_get_next_sibling(order_node, env);
 
 if(!list) return sort_error(env);
 
 axiom_node_t* current = axiom_node_get_first_child(list, env);
 
 if(!current) return sort_error(env);
 
 int i;
 
 a = AXIS2_MALLOC(env->allocator,
                  sizeof(long int) * MAX);
 
 for(i = 0; i < MAX && current; i++)
 {
  axis2_char_t *str = get_string(current, env);
  a[i] = strtol(str, NULL, 10);
 
  current = axiom_node_get_next_sibling(current, env);
 }
 
 int N = i;
 
 if(axutil_strcmp(order_str, "asc"))
  return build_sort_response(env, N, 1);
 else if(axutil_strcmp(order_str, "des"))
  return build_sort_response(env, N, -1);
 else
  return sort_error(env);
}

After parsing the input you should calculate and prepare the response of the service.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* Generate the response */
axiom_node_t *
  build_sort_response(const axutil_env_t *env, int N, int order)
{
 axis2_char_t value_str[255];
 axiom_node_t *main_node;
 int i, j;
 
 for(i = 0; i < N; i++)
  for(j = 1; j < N; j++)
   if((a[j] - a[j-1]) * order > 0)
 {
  long int temp = a[j];
  a[j] = a[j-1];
  a[j-1] = temp;
 }
 
 axiom_namespace_t *ns1 = axiom_namespace_create(env, "http://axis2/test/sort", "ns1");
 
 axiom_element_create(env, NULL, "result", ns1, &main_node);
 
 for(i = 0 ; i < N; i++)
 {
  axiom_node_t *value_node;
 
  sprintf(value_str, "%ld", a[i]);
 
  axiom_element_t *value_ele = axiom_element_create(env, main_node, "value", NULL, &value_node);
  axiom_element_set_text(value_ele, env, value_str, value_node);
 }
 
 AXIS2_FREE(env->allocator, a);
 
 return main_node;
}

That’s it now we have created the service, but we need to create the service descriptor services.xml

1
2
3
4
5
<service name="sort">
 <parameter name="ServiceClass" locked="xsd:false">sort</parameter>
 <description>Sort service example.</description>
 <operation name="sort"/>
</service>

Here’s the code of the service: sort_service.c and the descriptor: services.xml.

Then compile the service using gcc

gcc -shared -olibsort.so -I$AXIS2C_HOME/include/axis2-1.3.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver sort_service.c

The environment variable AXIS2C_HOME should be set to the axis2 installation folder.

Copy libsort.so and services.xml to folder AXIS2C_HOME/services/sort/.

Now start the axis server or restart if it’s already running, buy executing axis2_http_server. And check if the service is correctly deployed by checking http://localhost:9090/axis2/services.

Now that the service is running fine we can start creating the client.

Client

First we should set the properties and create the svc client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 const axis2_char_t *client_home = NULL;
 axis2_svc_client_t* svc_client = NULL;
 axiom_node_t *payload = NULL;
 axiom_node_t *ret_node = NULL;
 
 /* Create environment */
 axutil_env_t *env = axutil_env_create_all("sort_client.log", AXIS2_LOG_LEVEL_TRACE);
 
 /* Location of the service */
 axis2_char_t *address = "http://localhost:9090/axis2/services/sort";
 printf("Using address : %s\n", address);
 
 /* Creating options */ 
 axis2_options_t *options = axis2_options_create(env);
 axis2_endpoint_ref_t* endpoint_ref = axis2_endpoint_ref_create(env, address);
 axis2_options_set_to(options, env, endpoint_ref);
 
 /* Creating svc client */
 client_home = AXIS2_GETENV("AXIS2C_HOME");
 if (!client_home && !strcmp(client_home, ""))
 {
  printf("AXIS2C_HOME not set\n");
  return -1;
 }
 svc_client = axis2_svc_client_create(env, client_home);
 
 if (!svc_client)
 {
  printf("Error creating service client\n");
  AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:"
    " %d :: %s", env->error->error_number,
    AXIS2_ERROR_GET_MESSAGE(env->error));
  return -1;
 }
 axis2_svc_client_set_options(svc_client, env, options);

Then build the request.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
axiom_node_t *
   build_om_request(const axutil_env_t *env)
{
 axiom_node_t *main_node;
 axiom_node_t *order_node;
 axiom_node_t *values_node;
 axis2_char_t value_str[255];
 int i;
 
 
 axiom_namespace_t *ns1 = axiom_namespace_create(env, "http://axis2/test/sort", "ns1");
 
 axiom_element_create(env, NULL, "sort", ns1, &main_node);
 
 axiom_element_t *order_ele = axiom_element_create(env, main_node, "order", NULL, &order_node);
 axiom_element_set_text(order_ele, env, "des", order_node);
 
 axiom_element_t *values_ele = axiom_element_create(env, main_node, "values", NULL, &values_node);
 
 int N = 20;
 
 for(i = 0 ; i < N; i++)
 {
  axiom_node_t *value_node;
 
  sprintf(value_str, "%ld", i + 100);
 
  axiom_element_t *value_ele = axiom_element_create(env, values_node, "value", NULL, &value_node);
  axiom_element_set_text(value_ele, env, value_str, value_node);
 }
 
 return main_node;
}

Send the request.

1
ret_node = axis2_svc_client_send_receive(svc_client, env, payload);

Here’s the code of the service: sort_client.c. Now compile the client.

gcc -o sort_client -I$AXIS2C_HOME/include/axis2-1.3.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver sort_client.c -ldl -Wl,--rpath -Wl,$AXIS2C_HOME/lib

Run it

Run the client to see what happens.

What happens if the client sends an empty request?

Tags: , , , ,

This is a getting started tutorial to Windows Communication Foundation (WCF) Services. I have discussed a simple service to calculate the area of a rectangle; yup, very simple ;)

1. First you need to download and install Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation).

Oops, looks like it needs a windows validation (bit of a problem if you have a pirate copy :P )

2. Once the installation is complete, start Visual Studio to create the project.

Goto File->New->Web Site, and you’ll see a new template called WFC Service.

Click OK to create an empty WCF Service.

3. Time to get started with the coding

Service.svc

<% @ServiceHost Language=C# Debug="true" Service="GeometryService" CodeBehind="~/App_Code/Service.cs" %>

Only a small change here – the name of the service

Web.config

<?xml version="1.0"?>
 
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <system.serviceModel>
    <services>
      <!-- Before deployment, you should remove the returnFaults behavior configuration to avoid disclosing information in exception messages -->
      <service name="GeometryService" behaviorConfiguration="GeometryServiceBehavior">
        <endpoint contract="IGeometryService" binding="wsHttpBinding"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="GeometryServiceBehavior" >
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
 
  <system.web>
    <compilation debug="true"/>
  </system.web>
 
 </configuration>

Enable metadata publishing and change the name of the service.

Service.cs

using System;
using System.ServiceModel;
using System.Runtime.Serialization;
 
// A WCF service consists of a contract (defined below as IMyService, DataContract1), 
// a class which implements that interface (see MyService), 
// and configuration entries that specify behaviors associated with 
// that implementation (see <system.serviceModel> in web.config)
 
[ServiceContract()]
public interface IGeometryService
{
 [OperationContract]
 int GetArea(Rectangle rect);
 [OperationContract]
 int GetPerimeter(int width, int height);
}
 
public class GeometryService : IGeometryService
{
 public int GetArea(Rectangle rect)
 {
  return rect.Area();
 }
 
 public int GetPerimeter(int width, int height)
 {
  Rectangle rect = new Rectangle(width, height);
  return rect.Perimeter();
 }
}
 
[DataContract]
public class Rectangle
{
 int width;
 int height;
 
 public Rectangle(int width, int height)
 {
  Width = width;
  Height = height;
 }
 
 [DataMember]
 public int Width
 {
  get { return width; }
  set { width = value < 0 ? 0 : value; }
 }
 
 [DataMember]
 public int Height
 {
  get { return height; }
  set { height = value < 0 ? 0 : value; }
 }
 
 public int Area()
 {
  return Height * Width;
 }
 
 public int Perimeter()
 {
  return 2 * (Height + Width);
 }
}

This is the code for the service.

4. Run the service – click F5 :)

This is what you get on the browser. So, lets do what they want.

5. Run the following on you command on Visual Studio Command Prompt

svcutil.exe http://localhost:1479/GeoWFCService/Service.svc?wsdl

Watch out, the path might be different ;) . And if you don’t know what Visual Studio command prompt is

6. Let’s create the client

Create (or rather add) a new project; this could even be a website

7. Then run the service – Ctrl + F5

8. Add a web reference to the service

8. Copy the GeometryService.cs created by svcutil in step 5 to the clients working (main) folder and add them to the project

You should also copy the configurations of output.config created by svcutil to app.config

9. Again time for coding

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
namespace GeoWFCClient
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
  }
 
  private void calculateButton_Click(object sender, EventArgs e)
  {
   GeometryServiceClient gsclient = new GeometryServiceClient();
 
   /* The overloaded constructor of Rectangle is not present here */
   Rectangle rect = new Rectangle();
 
   rect.Width = Int32.Parse(widthTextBox.Text);
   rect.Height = Int32.Parse(heightTextBox.Text);
 
   areaTextBox.Text = gsclient.GetArea(rect).ToString();
   perimeterTextBox.Text = gsclient.GetPerimeter(rect.Width, rect.Height).ToString();
  }
 }
}

Set the textboxes and labels with appropriate names.

10. When you compile you’ll get a set of error because some assemblies are not referenced. Add references to them

11. Now see how it works

Start the service if haven’t done so already, and run the client

Wow! It works :D

Ok, hope you learned something with this and I got to go study for exam :P

Tags: , , , , ,

This is the AutoIt script I wrote to test my MARC(Millennium All-Island Robot Competition) robot -see previous post- through all the given batch runs. I posted this code so that anyone interested can use this to test his robot.

Tags: , , ,

ALV Grid lets you get subtotals and totals of columns, but you might often need to get averages and percentages among other not so frequent requirements.

It’s possible to get averages (or sub-averages) instead of subtotals you can use field_cat-do_sum = 'C'. in place offield_cat-do_sum = 'X'. which you use to get subtotals.

But what if you need to get a percentage; for example, you are given number of students present in each class and the total number of students in each class (which is not the same) and you need to get the percentage present in each class as well as the total of all class, which is obviously not the sum of all percentages – you must divide the total number present by the tatal number of students in the school. You can’t do this in the traditional way, but this isn’t very hard.

You can use the method get_subtotals, since this method returns a reference you can use it to change the values displayed as subtotals to what ever you want, not just percentages – ratios, powers, logarithms, anything you want. I haven’t still tested whether the values you’ve changed are changed back, when you hide columns (or do something with the ALV grid) in the ALV grid after it’s been displayed.

This is the code


CREATE OBJECT gr_alvcon
  EXPORTING container_name = 'ABC'. "Name of the custom container
  
CREATE OBJECT gr_alvgrid
  EXPORTING i_parent = gr_alvcon.

CALL METHOD gr_alvgrid->set_table_for_first_display
    EXPORTING
      is_layout = ps_layout
    CHANGING
      it_fieldcatalog = fieldcat
      it_sort = it_sort
      it_outtab = it_delsm[].

DATA : total TYPE REF TO data,
       subto TYPE REF TO data.

FIELD-SYMBOLS <ftotal> TYPE STANDARD TABLE.
FIELD-SYMBOLS <fsubto> TYPE STANDARD TABLE.
DATA wa_tot TYPE t_delsm.

CALL METHOD gr_alvgrid->get_subtotals
    IMPORTING ep_collect00 = total
              ep_collect01 = subto.
ASSIGN total->* TO <ftotal>.
ASSIGN subto->* TO <fsubto>.
  
LOOP AT <ftotal> INTO wa_tot.
  wa_tot-delpc = wa_tot-delpr * 100 / wa_tot-totpr. " Set any value for this
  MODIFY <ftotal> FROM wa_tot INDEX sy-tabix.
ENDLOOP.

CALL METHOD gr_alvgrid->set_ready_for_input
    EXPORTING i_ready_for_input = 1.

Hope this suits your need.

There are many ways of customizing the values in subtotals and totals. I’ll later put information about them also.

EDIT

Since there had been some questions about the above code and using it with REUSE_ALV_GRID_DISPLAY (see comments), I thought of adding a piece of code that might help you. This will set an event and change the subtotals during that event.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
* Events
CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
  EXPORTING
  i_list_type = 0
  IMPORTING
  et_events = v_events.
 
READ TABLE v_events INTO wa_event WITH KEY name = 'END_OF_PAGE'.
wa_event-form = 'SET_DEL_PERC'.
MODIFY v_events FROM wa_event TRANSPORTING form WHERE name = wa_event-name.
 
*Set the percentages for subtotals
FORM SET_DEL_PERC.
	DATA : total TYPE REF TO data,
         subto TYPE REF TO data,
         subt1 TYPE REF TO data,
	       gr_alvgrid TYPE REF TO cl_gui_alv_grid.
	FIELD-SYMBOLS  : <ftotal> TYPE STANDARD TABLE,
                   <fsubto> TYPE STANDARD TABLE,
                   <fsubt1> TYPE STANDARD TABLE.
	DATA wa_tot TYPE t_delsm.
 
	CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
		IMPORTING
			e_grid = gr_alvgrid.
 
 
	CALL METHOD gr_alvgrid->get_subtotals
	    IMPORTING ep_collect00 = total
	              ep_collect01 = subto
	              ep_collect02 = subt1.
 
  ASSIGN total->* to <ftotal>.
  ASSIGN subto->* to <fsubto>.
  ASSIGN subt1->* to <fsubt1>.
 
* Use a method to calculate percentages if number of levels with subtotals increase
	LOOP AT <ftotal> INTO wa_tot.
    PERFORM cal_del_per CHANGING wa_tot.
 
	  MODIFY <ftotal> FROM wa_tot INDEX sy-tabix.
	ENDLOOP.
 
	LOOP AT <fsubto> INTO wa_tot.
    PERFORM cal_del_per CHANGING wa_tot.
 
	  MODIFY <fsubto> FROM wa_tot INDEX sy-tabix.
	ENDLOOP.
 
	LOOP AT <fsubt1> INTO wa_tot.
    PERFORM cal_del_per CHANGING wa_tot.
 
	  MODIFY <fsubt1> FROM wa_tot INDEX sy-tabix.
	ENDLOOP.
 
CALL METHOD gr_alvgrid->set_ready_for_input
		EXPORTING i_ready_for_input = 1.
ENDFORM.

Hope this helps

Tags: , , , ,

Arrays in ABAP

Recently I came across a program which reads a table to get weekly information about raw material availability into itab with a row for each material. The table contained data with a reference to the day of the week as 1 for Monday, 2 for Tuesday, …, and 7 for Sunday. The program used a case statement to assign the material availabilities to each day using the day-code, which was a very long code and lacked understandability, and I was supposed to add another functionality to this.

Try to do it the easy way than coding the same thing 7 times, I found that field-symbols would make the difference.

Here is an example of what I did :

FORM ASSIGN_TO_DAYS.
DATA : BEGIN OF it_data,
         day1 TYPE P,
         day2 TYPE P,
         day3 TYPE P,
         day4 TYPE P,
         day5 TYPE P,
         day6 TYPE P,
         day7 TYPE P,
       END OF it_data.
FIELD-SYMBOLS : <fs_day>.
DATA : BEGIN OF pointer,
         table(6) TYPE C VALUE 'IT_DATA',
"Make sure that all reference texts are captal
         sep(1) TYPE C VALUE '-',
         head(3) TYPE C VALUE 'DAY',
         day TYPE N,
       END OF pointer.
  LOOP AT st_mat.
    pointer-day = st_mat-daynr.
    ASSIGN (pointer) TO <fs_day>.
    ADD st_mat-menge TO <fs_day>.
  ENDLOOP.
ENDFORM.

Tags: , , ,