Simple Java Combinations Algorithm Code - Calculate Combinations of Elements in an Array

Below is some code I wrote recently to calculate the different combinations of elements in an Array. It is a simplified and straightforward recursive solution.

A recursive solution has 2 important piecies: a base case, and a recursive step. Here is an example of how the code below executes:

given: [1,2,3,4]

Recursive Step - Iterate through each element and break it out, leaving the rest of the elements
(first iteration)
1 [2,3,4]
2 [1,3,4]
3 [1,2,4]
4 [1,2,3]

(second iteration)

1 2 [3,4]
1 3 [2,4]
1 4 [2,3]

…. etc

The recursive step is defined in plain english as just remove a value, then call the function again on the rest of the list (with this element removed).

In the base case, once we have an array the size of length 1, we just simply return the array - so simple!

There is a key piece of code that, given an element and an array of arrays, prepends the element to each array. i.e.

1, [[5,6], [7,8], [3,4]] –> [ [1,5,6], [1,7,8], [1,3,4] ]

Pretty simple.

import java.util.ArrayList;

public class Combination {
public ArrayList<ArrayList<Object>> compute(ArrayList<Object> restOfVals) {
if(restOfVals.size() < 2) {
ArrayList<ArrayList<Object>> c = new ArrayList<ArrayList<Object>>();
c.add(restOfVals);
return c;
}
else {
ArrayList<ArrayList<Object>> newList = new ArrayList<ArrayList<Object>>();
for(Object o: restOfVals) {
//make a copy of the array
ArrayList<Object> rest = new ArrayList<Object>(restOfVals);
//remove the object
rest.remove(o);
newList.addAll(prependToEach(o, compute(rest)));
}
return newList;
}

}
private ArrayList<ArrayList<Object>> prependToEach(Object v, ArrayList<ArrayList<Object>> vals){
for(ArrayList<Object> o : vals) {
o.add(0, v);
}
return vals;
}
public static void main(String args[]) {
ArrayList<Object> i = new ArrayList<Object>();
i.add("1");
i.add("2");
i.add("3");
i.add("4");
Combination c = new Combination();
ArrayList<ArrayList<Object>> ff = new ArrayList<ArrayList<Object>>();
ff = c.compute(i);
System.out.println(ff.size());
System.out.println(ff);
}
}

Tags: , , , , ,

How Click Streams are like DNA

How Click Streams are like DNA

Introduction:

When doing web analytics, its easy to get overwhelmed with data. Using the proper data structures to store and analyze data is key to keeping things manageable. In this short paper, I present a new idea of a data structure to model user click streams as a series of ‘gene-like’ events, which lends itself nicely to analyzing these user click streams. A click stream refers to all of the clicks that a user makes on the website for a given web-browsing session. An example is a user opening an e-commerce website, navigating through a few pages, and ultimately exiting the website. Looking at clickstreams as an ordered series of small events allows us to capture user experiences over time as opposed to the normal approach of using aggregate numbers at specified time points. Similarly, it allows us to do operations that we are used to, such as ‘string matching’ where we simply look for similar sequences of events to calculate similarity between user experiences, which would otherwise be much more troublesome.

Assumptions:

While not necessarily proven across websites, my leading theory is that a user’s experience on a given website dictates his percentage to pay money. For instance, if I am on an e-commerce site and I see the most popular selling shirt, I may be more likely to buy that shirt than if I see the least popular shirt. In this, my probability to pay is dictated by the things I see on the website, and not necessarily by my pre-existing condition (although that may play a factor as well).

Body:

Often, there is too much data to capture for every user. For instance, a users mouse may move across thousands of pixels in a given session, and a user may click hundreds of different times, and each of these has a time characteristic associated with it.

So let’s start by making the model simple, and we’ll make a few iterations to make it better.

Lets say we took every URL on our website, and assigned it a number, and lets call this number the URL_ID. For a fictional site, we could make a table of all the urls something like this:

URL_ID URL
0 mypage.com
1 mypage.com/store
2 mypage.com/store/girls
3 mypage.com/store/guys
4 mypage.com/sweaters/guys
5 mypage.com/sweaters/girls
6 mypage.com/shirts/guys
7 mypage.com/shirts/girls
…. etc

Now, for each of these urls, there are many events that a user can take (watch a movie, select text, press buttons, submit forms, etc), but for simplicity, lets say that a user is limited to clicking links. So, we would make another table that assigned every link on our website a specific number as well, lets call this number LINK_ID. We could then create a table like this:

LINK_ID URL_ID
0 0 (mypage.com header link)
1 0 (mypage.com footer link)
2 0 (mypage.com main link for guys sweaters)
3 0 (mypage.com main link for girls sweaters)
4 1 etc…
5 1
6 1
etc

In the table above, we show that a given URL has many links a user can click on.

Now, let’s model a users click stream using our fancy new click event ids. So lets take the scenario where a user comes in and navigates through these pages in this order:

(User types url into address bar and presses enter)
mypage.com

mypage.com/store/girls

mypage.com/sweaters/guys

mypage.com/shirts/girls
(User exits)

Now, we can translate this users clickstream into a series of integers. We do this simply by substituting in a LINK_ID for each link that a user clicked on.

So we started with:

mypage.com

mypage.com/store/girls

mypage.com/sweaters/guys

mypage.com/shirts/girls

and each of these click events can be translated into an integer just by looking up the proper URL_ID and LINK_ID in the table that we made previously for our website.

mypage.com (URL_ID = 0)
(LINK_ID = 1)
mypage.com/store/girls (URL_ID = 2)
(LINK_ID = 4)
mypage.com/sweaters/guys (URL_ID = 4)
(LINK_ID=5)
mypage.com/shirts/girls (URL_ID=7)

In this case, if we just take the URL_IDs and LINK_IDs we have something that looks like this:

0
1
2
4
5
7

Lets just write those as an array of numbers, namely:

[0,1,2,4,5,7]

So in this case, we have condensed the users clickstream into a series of numbers, cool! This captures the order of clicks and the order of urls that a user experienced on our site. Now lets say we had another user, let’s call him user2, that had a click stream for one session like:

[0,2,4,5,7]

Do you see any advantages to representing user clickstreams this way? Many things become apparent when we look at these two streams, here are a few:

- Both users sessions ended on the 7 event

-Maybe this is the main drop-off of our website?
- Both users entered on the home page

- Does our entrance page affect the experience?
- Both the users visited pages 0,2,4,5,7

- Are pages 0,2,4,5,7 the user flow that optimizes revenue for my business?

These are just a few questions that could become easily apparent by analyzing click streams in this manner.

If we wanted to compare the similarity of two user experiences:

user1 = [0,5,4,3,2]
user2 = [0,5,2,5,1]

We could simply use many well-known string matching algorithms to compare how similar the experiences were (Levenshtein edit distance, Sellers edit distance, the Hamming distance, the longest common subsequence length, the longest common substring length, and the pair distance metric)! Each algorithm would give us different stats.

Imagine we had one event that we prized, such as users buying an item at our store, lets say that event was 9, and we had two user click sessions:

user1 [0,2,5,6,7,2,3,2,3,2,5,4,9]
user2 [0,6,3,2,3,2,5,9]

In this case, we see two unique user experiences on our site that led them to buy an item from our store. One valid way to look at the data may be to find the longest common subsequence, and correlate that with a buying event, namely:

3,2,3,2,5 (longest common subsequence)

If this subsequence was highly correlated with users reaching ‘9’ i.e. purchasing a product, we could then make new users to our site have a similar experience and hopefully convert more poeple to buy at our store, increasing our buyers conversion and getting more people to buy! This leads to the title of the paper, in that we could call this longest common subsequence a ‘gene’ encoding for paying users.

We could change events for users, based on previous click data.

Now, much of this is being done and has been done already many times. The novel part of this idea is to look at events as a series of ordered integers, to easily pick out certain genes and match users to each other through their clickstreams.

So now we can make the model a little more sophisticated. Let’s add many sessions, so each user session could be a string like we showed:

[user first session] [user second session] [user third session]

could look something like

[0,2,5,3,4,5,4] [2,3,4,5,2,3] [2,3,4,2,3]

In this case, a user may visit the site first on the weekend, then not log in for many months, then log into the site on a wednesday, then many months later log into the site again on a tuesday. Inotherwords, the timing of a users actions would be a critical set of data to add. Let’s do that. We use the acronym SBV (seconds between visit) to represent the time elapsed between user visits.

[0,2,5,3,4,5,4] SBV1 [2,3,4,5,2,3] SBV2 [2,3,4,2,3]

And of course, SBV is simply a number of seconds, so lets put that in

[0,2,5,3,4,5,4] 3000 [2,3,4,5,2,3] 5000 [2,3,4,2,3]

However, instead of one long number like the one above, in some cases we like to analyze timing events seperately from the events themselves:

[SBV1, SBV2] = [3000,5000]
[SESSION1] [SESSION2] [SESSION3] = [0,2,5,3,4,5,4] [2,3,4,5,2,3] [2,3,4,2,3]

Adding additional data into the model can easily be done. This is only a start to thinking about user click streams as ‘genes’.

Nathan

Here are some further ideas:

- It may be easy to generate unique ids for urls simply by taking an MD5 of the url
- Finding the optimal subsequences of user experiences online
- Take into account other events that a user can take on a web page
- Figure out how to effectively use both timing and click sessions together in the same string

Tags: , , , , ,

Ruby - Cron Not Working For Ruby Script

If you try to use ruby in a cron script, there are certain errors or ‘gotchas’ that you should look out for. Hopefully this short ruby cron guide will save you a few minutes of debugging. The main problems for a ruby script in a cron file are improperly set permissions, improper environment, no new-line at end of cronfile, or an error in ruby script itself. Say i have a file in

/home/myuser/myfolder/myrubyscript.rb

First, make sure that this file has the proper permissions, i.e. read and execute permissions for the user that is running the cron. If you aren’t sure, just use 755 permissions, i.e.:

sudo chmod 755 /home/myuser/myfolder/myrubyscript.rb

Now that this script can be executed by cron, now you should set the environment properly, namely, that the environment when cron runs is different from your environment! Things such as the GEM_HOME path may not be set properly. To see your paths, make another cron job like this:

* * * * env > /home/myuser/cronenv.txt

This will create a file called cronenv.txt that lets you see what your environment is like when the cron job runs. You may need to set your PATH and your GEMHOME variables inside your crontab, so your cronfile should look something like this:

GEM_HOME=/usr/lib/ruby1.9.1/gems/1.9.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * /usr/bin/ruby /home/myuser/myfolder/myrubyscript.rb

Another gotcha is that

the last line of your cronfile should be a line return

Check the /var/log/syslog to see if the cron job is running, and in parenthesis it should say what user it is running as. Make sure this user has the proper permissions as stated earlier (i.e. 755 on the file).

If you have done everything above and things still aren’t working, it probably means that there is an error inside of your file. A trick is to simply surround your topmost code in a begin / rescue block, and open a file a write any exceptions to a file, something like this:

f = File.open("/home/myuser/myerrors.txt","w")
f.puts "at the top of my file"
begin
.... my regular code....
rescue Exception=>e
f.puts "#{ e.message } #{ e.backtrace.join("\n")} "
end

Tags: , , , , , , , , ,

Tricks Learned from Lessons Learned - Lean Startups

The Lean Startups presentation today was astoundingly good — even across all the intertubes between SF and NY, through justin.tv servers to a 3G network to an iphone to a laptop to an LCD in the McKinsey building on 485 Madison Ave, the guiding principles of lean startups shined through. And I learned a few nice tricks in the process.

I would summarize the guiding mantra of lean startups as “finding what the user wants quickly and cheaply”. Often, products are built before knowing what the user wants, while the costs run high. Lean Startupers preach that your business must focus around asking the user what he or she wants, getting good estimates that many people want this, and keeping users by your side during the design and development of the actual product. There is a whole agile mantra to the development side of things as well, but here I just share thoughts on higher level hacks and tricks.

Its a constant user-feedback loop. Iterate iterate iterate in small steps, keep evolving your idea and keep your codebase lean and small — and never guess what you think users will need or want.

Easy right? Are you going to build your whole product and then buy ads to drive traffic so people can just SEE your product and hope that someone out their likes it? No need!

The FlowTown (flowtown.com) guys were awesome, I feel like they are true hustlers of the net and paradigms of the lean startup movement, and they shared a really nice trick to getting feedback before you have a product — simply mock everything out — instead of building the entire backend for your product, just build the front end and make it look nice, and measure user actions. So craft some html and throw it up on a web page and measure how many times people click the ‘Buy’ button on your website, or how many times people even read your about description. Maybe try to capture their e-mail address in the process. This gives you estimates toward measuring the demand of your market and your product, without having written a single line of code! (HTML isn’t code, remember)

I really respected the Aardvark presentation — I enjoy seeing ‘true’ and ‘real’ people showing exactly how they came upon their ideas, and I felt this resonating sense with Aardvark when they showed us their 8 or so starting ideas written down on a piece of paper; it was awesome to see that they do it just like anyone else, write down your ideas, decide on the best one, and go with it!

The KISSMetrics (kissmetrics.com) team had an awesome presentation as well - I enjoyed the sense I got from their founder talking about ‘pivoting’ — a decision to change the overall vision and product focus of the company — which many would think a daunting task, they had already pivoted their web analytics product twice to better suit the needs of their clients.

In fact, pivoting seems scary, but in reality the closer you stay with possible clients and listen to what they need, the less scary it becomes — people are saying to you ‘this is what i need’, so you go out and build that. The problem arises when people don’t know what they need, or think they need something when they need something entirely different. I haven’t figured this one out, but I imagine that if you listen closely enough, you will hear the true need and solve that problem, as opposed to the possibly superficial problem that may come from a naive client’s lips.

The other thing that I liked about KMs presentation was their focus on defining the archetype of their customer, basically they would take a picture of a person they thought would use the product, write his or her job description, and then append a few ‘truisms’ why this person liked the product. For example, their first product was built for a ’social application developer’ — this caption was appended to a picture of a 20-something guy with long hair, and they said something like ‘needs metrics to measure actions on his webapp’. Simply small quips defining the need they were filling.

I think its extremely important to define who you are serving and why they use your product, and they hit this one out of the park.

I do have some questions still though:

When trying to judge the merits of an idea:
- How do you get people to view your product by spending very little money, say, driving traffic to a website? After all, views don’t come easy, especially if you have a more niche target audience.
- How much data does one need before he/she can be sure that its enough to move forward and develop?

When deciding whether to pivot:
- How do you know when your business isn’t working? How long?
- If you only have mild success, do you need to pivot or is that the extent of your business?

Tags: , , , ,

The Internet Trends - Niching, Layering, Hierarchy.

Isn’t it amazing how much knowledge is actually on the internet? You can google just about anything these days - often I have what I think is a semi-original thought, and can usually find someone thinking the same thing in a matter of minutes.

The fact is, we are quickly reaching the point where those quick ‘first layer’ thoughts or questions that all of us have are, or can be answered by, the internet. By first layer, I mean quick thoughts or questions that pop up in our minds on a daily basis, as opposed to questions that come when we are intensely focused on a particular area or in a particular field of expertise.

What is the impact of this? Well, what it means is that to get noticed, you need to start ‘niching’. Yep - this is talked about all the time in online marketing - targeting a specific niche to talk about, filling in the gaps of the knowledge of the internet on particular focused topics.

The second trend, which is a more predictable one due to natural heirarchy, is the layering that is being built on top of the internet. First there is the information. Then there are information aggregators - then there are aggregators of aggregators, and search of search engines. There is infrastructure being built on top of the cloud to manage it all. We built servers and browsers to handle the responses and the requests, and now we have networks and clouds of servers that can easily pass the data back and forth, and scale on and off demand flexibly.

The question is, what is the next layer that is being built? How will the browser / request / server model change? What is the next layer that will be built on top of the internet’s vast amounts of aggregated information?

How far can one think?

I have recently been paying more attention to my general thinking patterns, and am trying to deduce the optimal balance between thinking and experience when making a decision.

Experience is simply a process of gathering more information, while thinking is the process of assimilating and structuring that information but also thinking is imagining and recreating experiences. When one wants to make a decision, usually one turns to thinking and reasoning through the space. To analogize, to me its like you are a small lighted circle on a map - this is your small circle of ‘understanding’ or the whole picture you see in your mind and what you understand comfortably; and there is a fog that surrounds your little circle of understanding on all sides, covering up the surrounding territory. Thinking is the process of moving on different roads and exploring those fogged areas, so that you see the whole picture. Its important to note that it takes critical and open thinking to ‘push back’ this fog to expand your understanding and knowledge of the whole picture. This process consists basically of using logical reasoning and assumptions to think your way through the fog, and if you get stuck, you try to call on your other experiences or even ‘imagine’ how something would be to keep thinking.

However, because of how our minds work, it is often difficult to push the fog back very far - the reason is that we tend to think stereotypically and use lots of assumptions. Similarly, often it becomes difficult to properly imagine situations, let alone assess these imagined situations. Assumptions help us limit, focus, and direct our thinking, but they also prevent us from taking other roads and exploring the fog in all directions. Assumptions, then, are almost like the roads themselves - they let us think in a certain direction, much like taking a road and exploring a territory in one direction - you can’t veer from the path. However, without assumptions, we have no direction - they are very necessary. The farther and farther you move from your original starting point, what usually tends to happen is that the assumptions you make become weaker and more imagined, making it harder to move through the fog. This is why experience is so key.

Continuing with the same analogy, experience is then like a ’spotted highway’ on the map. The reason is that its much easier to understand when one experiences something first hand, its not like you are ‘fighting back’ the fog to think through it, but rather, experience just happens and understanding comes naturally - thats why its a highway, because you can understand a lot just by experiencing it, much like a highway in that you can travel great distances very quickly. However, the highway is ’spotted’ because really, experience teaches a lot of random stuff - it doesn’t necessarily carve out a large circle of understanding, but many such smaller circles of understanding scattered through the territory, that its up to you to connect.

So we mentioned that the roads in our analogy are the ‘assumptions’ we make, because they help direct our thinking. What we can do then is be self-aware of the assumptions we are making, and then challenge these assumptions. By doing this, instead of being stuck on a one-way road into the fog, we start creating side-paths that we can take and explore, which makes then our thoughts have lots of ‘branches’. Every time we drop an assumption, the possibilities open up for us to explore new options, but, of course, our path of reasoning becomes less defined; thus at some point we usually create a new assumption then (different from the old one) to create a new path for ourselves into new areas of the fog.

So what is the optimal balance between thinking and experience? This is an extremely hard question, but to answer it, I would say that more information and experience is always a better thing no matter what; that said, I don’t necessarily have a good answer, but more a quip like cliche. I would say that thinking is only necessary when a decision needs to be made, and more experience is necessary when thinking cannot provide a decision. In other words - if you can’t decide, get more experience, then decide. Simple? Not really.

Tags: , , , , , , ,

Modeling a Path to Successful

I recently read this blog entry http://lethain.com/entry/2009/jul/31/success-and-dancing-shoes/ and starting thinking on what success was REALLY about. The article had much truth to it, saying that one must position oneself amongst the right people, and of course must be willing to work hard, and there should be a sprinkle of luck. I started thinking how to model a path of success.

But honestly, I have a completely different model of the factors of success.

A key ingredient in the model of success is ‘the goal’.

What do I mean by ‘the goal?’

I mean that at some point, there needs to be an idea that can be realized as something concrete that provides real value to people (or businesses). There has to be a direction that is being moved in to create this value. If you want to be successful, you need to be associated (and possibly contributing to) the right goal.

A goal can be a new toy you are going to produce, a new internet startup based around a novel idea, or anything that essentially a group of people can use as a direction to move towards creating something of concrete value. Most of my examples will be business oriented, but this doesn’t have to be the case. All that matters is that there must be value produced.

First, you should ask yourself, is there anyone considered successful who has not been associated with a goal? I can’t think of any.

Now, once you accept that a goal has to exist, the question of ‘how do I become successful’ instead turns into something else. It becomes a matter of being associated with the right goals/directions/ideas, as well as potential goals/directions/ideas.

Everyone is part of many goals today - in fact, you should probably ask yourself ‘What goals am I pursuing?’ - one of them, if you are employed, is your employers goal of doing whatever it is the company is trying to accomplish.

The people who you surround yourself with are essentially your ‘pool’ of potential goals you can pursue. Maybe one of them is entrepreneurial, and has a goal of starting a company. Then you also have a potential to be in that company and pursue that goal.

However, the main thing you should realize is that you have your own goals! You can have an idea of something of value, and share that goal with others and pursue that goal. The important questions to ask oneself are “how can I do this better?”, or if a problem presents itself, realizing that solving that problem for yourself is also probably a problem for others, and it is a small step from solving a problem to creating a new goal of solving this problem on a larger basis.

Thus, success is about the intersection of a two things:
1. How well your defined goal provides concrete value to others
2. How well you and the people you surround yourself with can pursue that goal

The first is about measuring the usefulness of the goal - will people like this new toy? Will people use this internet service? This can be a very hard estimation, but you can improve and hone it over time with feedback.

The second is about how well you can solve the subproblems that creep up and get in the way of the greater goal. With a solid team of smarter, experienced, and well-tempered individuals, you will be able to handle these sub problems better. Some sub problems may be ‘how can I change the product to match the needs of what people are telling me they need/want?’, or ‘how can I tackle this technical challenge’ or ‘how can I get the next round of funding for our company?’

One must attach oneself to a goal, or create the goal and attach people to it. Success is merely the approach and carrying out of this goal.

Tags: , , , ,

Create a Django Dynamic Form with JQuery - Dynamic Field Addition and Removal

So I found a nice piece of Jquery - Jquery-Dynamic-Form ( http://code.google.com/p/jquery-dynamic-form/ ), and thought it would be just the thing to spice up the static forms on my latest venture (a django website, of course). So I downloaded the jquery file and tested it out, and I thought, to myself that it would be no problem to integrate - well, it took longer than I thought, but I finally got it to work nicely.

Here’s how I was able to integrate dynamic addition of form fields on my django form using jquery- dynamic-form:


0. First, fix the JQUERY. This particular jquery library used a ‘php’ style naming scheme for its variables - namely, something like:

<input type="text" name="myfield[]" id="0">
<input type="text" name="myfield[]" id="1">
<input type ="text" name="myfield[]" id="2" >

As you can see, it used the php array as the name - instead, i make a quick fix to the jquery to make it instead just do this naming scheme:

<input type="text" name="myfield0" id="0">
<input type="text" name="myfield1" id="1">
<input type ="text" name="myfield2" id="2" >

To do that was rather easy, simply change a couple lines in the jquery; to look like this:

/* Normalize field name attributes */
            if (!nameAttr) {
				jQuery(this).attr("name", "field" + fieldId);
			}

			if (!/\[\]$/.exec(nameAttr)) {
				jQuery(this).attr("name", nameAttr + fieldId);
			}

As you can see, we only changed 2 lines of code, so that it appends the ‘fieldId’ to the end of the name attribute.


1. Set-up the form template properly with jquery-dynamic-form (easy) - lets you clone whatever field you want, in my case, just a + and - buttons to click on to add / remove text fields on the fly (this template needs a dynamic element to it, but we’ll get to that in step 3)
The JQuery Stuff:

<script type="text/javascript" src="/media/js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/media/js/jquery-ui-1.7.2.highlight.min.js"></script>
<script type="text/javascript" src="/media/js/jquery-dynamic-form.js"></script>
<script type="text/javascript">
    $(document).ready (function() {
        $("#duplicate").dynamicForm("#plus", "#minus", {limit:6, createColor:"yellow", removeColor:"red"});

    });
</script>

The template form stuff:

<form method="post" action=".">
 <fieldset>
        <h3>My dynamic text fields</h3>

		<div id="fields">
		    <div class="field">
		        {{ dynamic_html }}
		        <p><span><div id="plus">Add Another <a href="">[+]</a></div>
		        <div id="minus">Remove <a href="">[-]</a></div></span></p>
                    </div>
               </div>
    <p><input type="submit" value="Build it!" /><br/></p>
 </fieldset>
</form>

As you can see, we dynamically create the guts of this template with a variable called {{ dynamic_html }} - I’ll show you what happens with this in a second.

But in general, its just some code that we generate that shows our bound form fields, but it works just like you think it would - clicking the plus adds a field, clicking the minus removes it, intuitive! Here is a quick preview:

A Preview of the Form

A Preview of the Form

2. When the form is submitted, the VIEW dynamically creates a form to match the submitted amount of fields. I used what i call the ‘type’ method to dynamically create the form- we’ll show you this in step three. When the form gets submitted, here is the view that handles it:

Here is the view code:

def myview(request, template_name='myapp/mytemplate.html'):

    if request.method == 'POST':
        #create the dynamic form class here on the fly
        form_class = make_dynamic_form(post=request.POST)

        form = form_class(data=request.POST)

        #this is the template that we insert into our general template
        dynamic_fields_template = make_dynamic_fields_template(form.data)

        if form.is_valid():
            #hooray! A Valid form - process the form fields as necessary!
           return HttpResponseRedirect('/')
    else:
        initial_vals = {'empty_textbox':'',}

        form_class = make_dynamic_form(post=initial_vals)
        form = form_class()
        dynamic_fields_template = make_dynamic_fields_template({'blog_url':''})

    dynamic_html = dynamic_fields_template.render(Context({'form':form}))
    return render_to_response(template_name,
                                {'form':form, 'dynamic_html':dynamic_html},
                                context_instance=RequestContext(request))

#Input: dictionary of fields into this method
#Output: Html (with our field variables not yet bound to context)
def make_dynamic_fields_template(fields):
    template_html = ""
    for f in fields:
        template_html += """
        <p id="duplicate">
        My Form Label {{ form.%s }}
        {{form.%s.errors}}
        </p>
        """ % (f, f)

    return Template(template_html)

Here you can see that we dynamically create our form on the fly from the POST information using a custom method that we show in the next step. If the form is valid, perfect, and you can process it like any other form. If it was the first time we accessed the page (and didn’t POST), then you can see that we simply create a form with one field on the fly, render the template for this one field, and then pass this dynamic_template inside the other template; this variable gets rendered it like a regular variable using {{ dynamic_html }} inside the template.

Why do we have to render the template on the fly? Well, if the template (with a bunch of new, say, text fields you added dynamically) doesn’t validate - well, then you need to return that form you just used (with its corresponding errors) - but you still want it to be a dynamic form, but the original template you used doesn’t know how many fields you added or removed dynamically (using jquery), or what their names are! Thus, we need to dynamically generate a template again from our new form, which we do by created the html and passing it into our template as a variable (and rendering it there)

2.5 To create the form on the fly, we use this method:
http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/ to create the form on the fly. You can see we override the ‘clean’ method; We validate all the dynamic fields, and if there are errors, assign the errors back to the individual fields (otherwise, errors would go in non_field_errors) - this is done using this technique: http://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

And here is how the form is created on the fly:

def make_dynamic_form(myfields={}):
    fields = {}

    #create the fields dynamically!
    for p in myfields.keys():
        fields[p] = forms.CharField(max_length=200, required=False, widget=forms.TextInput(attrs={'class':'text' }))
    #this creates our new form with the given fields
    newform = type('MyDynamicForm', (forms.BaseForm,), { 'base_fields': fields })

    #now lets define our clean method
    def clean(self):
        cleaned_data = self.cleaned_data

        #iterate through each value
        for val in cleaned_data.keys():
            if not val:
                continue;

             if (self.cleaned_data[val] is None) or (self.cleaned_data[val] == ''):
                    continue;

            # clean the individual value below

             ...run your own cleaning tests here....
             ...say it doesn't validate.....

             #we defined assign_error function to assign the error to the correct field
             self.assign_error(val,u'This is an error we want to attach to that specific dynamic field!')
             #this error goes in non_field_errors - we call this method anyway
             raise forms.ValidationError(u'Error!')

    #attaches an error to a specific field instead of non_field_errors
    def assign_error(self,val,msg):
        if not self._errors.has_key(val):
            self._errors[val]= ErrorList([msg])
            del self.cleaned_data[val]

    #create the methods for the form
    newform.clean = clean
    newform.assign_error = assign_error

    return newform

What we do here is create a fields dictionary, pass this dictionary into the ‘type’ function along with some other stuff, and we create our form. Now, we define the methods we want, and set these as attributes for the form, and finally return the new form. In this case, we defined the clean method, and also a helper method to assign the errors to their respective fields - otherwise, django would put all our errors in non_field_errors, because thats what happens when you raise form validation errors inside of the ‘clean’ method.

Thanks! Any questions / comments are welcome!

Tags: , , , , , , , ,

Expand a VMWare Partition Vista / Ubuntu

So I run Vmware on Vista with a virtual install of Ubuntu on an 8GB partition - well, the 8GB filled up, so I needed to expand the ext3 partition.

The three steps to take are:

1. Expand the VMWare partition using the vmware tool (comes with vmware workstation and others)
Here is a link that describes how to do this: http://4sysops.com/archives/expanding-a-virtual-vmware-disk/ . It is fairly easy to do.

The code looks something like this:

'vmware-vdiskmanager -x 10GB myDisk.vmdk'

2. Now, download a live cd that you can boot from, knoppix is the one I used http://knopper.net/knoppix-mirrors/index-en.html — just download an iso file of it. You’ll want to boot vmware from this iso, so what you do is in the Vmware Workstation sidebar, put this iso in the CD Drive (click on the CD drive and load this iso, easy!). Now you need to tell Ubuntu to boot from CD, so go to VM –> Power –> Power on to Bios. Now, this will start up the Vmware bios, now go to the boot menu and press the ‘+’ sign to move the CD Drive up to the top (so it boots first before the hard drive, so that ubuntu will start from this live cd iso that we downloaded).

3. Now Knoppix should be loading, (you may have to hit like ‘return’ to get it to start loading) - once its fully loaded, open up a terminal. type ‘gparted’ in the terminal to run gparted. Now it should show all your partitions and such. Unmount all the drives you need to do stuff with using:

su root

umount /dev/nameofdrive, i.e........ umount /dev/sda1

If the swap partition becomes an issue root, i.e. you need to delete it, you need to turn it off first, so just do:

swapoff -a

Now, make sure there are no partitions between the free space and the original partition you want to expand. Simply select the partition you want to expand and select how much you want to expand it! Then click ‘apply’ in gparted to actually do it, and it should take a while before saying completed.

If the swap partition is between the free space and the other partition, you will need to delete the swap partition and create a new one at the end of the free space.

Once you have hit ‘apply’ in gparted, and it tells you everything was successful, shut it down, and then go back to vm–>power –> power on to bios and reset your boot so that it doesn’t run from CD first anymore. Then restart and it should load up your regular installation (in my case vmware), but this time with more space for you to use!

Note: You should probably check that things are working, and you may have to make a few edits. First, you should type (as root, or on ubuntu use sudo as shown):

sudo fdisk -l
</pre>

This will list all the partitions you have, make sure its set up properly. Now, if you deleted a swap file, you should check to see if the new swap you created is being used:

free -m
</pre>

This should show how much swap is being used. If your swap is not on, well turn it on using 'swapon'. Use the command 'blkid' to check the names of your partitions, then edit the /etc/fstab file and make sure that the names of the partitions are all the same as the ones you saw when you used the blkid command. If they aren't, change the /etc/fstab file to the correct ones.

Tags: , , , , , , ,

C++ Eclipse Install CDT and MinGW GCC Plugin

I just succesfully installed c++ on eclipse using the CDT C++ plugin and MinGW compiler for windows Vista. There are a lot of plugins to get working. There were a few things that I had to set up, no doubt, so here are some notes for those of you trying to do the same thing:

0. Obviously you need to have downloaded eclipse first http://www.eclipse.org

1. Download the  Eclipse CDT Plugin http://www.eclipse.org/cdt/

2.  Now because I am on windows I need to install a c++ compiler (the CDT plugin doesn’t come with one!), so the recommended one is MinGW. Here is a link that says exactly how to install it, and exactly what you will need to install. http://www.mingw.org/wiki/Getting_Started. Note that there is an automatic installer.

At this point, DO NOT FORGET TO SET YOUR PATH VARIABLE! This is very easy on windows; http://www.java.com/en/download/help/path.xml this says how to do it.

If you happen to get the error:”Your connection appears to have dropped out. Reconnect your dial up or check your IE proxy settings.” then this means that sourceforge is having trouble downloading the file. What you should do is first make sure the installer is not on your desktop, retry it a few times, and then set your source forge default mirror settings - this can be done by signing up for a sourceforge account and then going to your account  https://sourceforge.net/account/ and clicking the Default Download Mirror under the main preferences page.

3. Now follow this guide to setting up the code environment - it is a little outdated but you should be able to follow it pretty easily:

http://www.codeproject.com/KB/tips/CPP_Dev_eclipse_CDT.aspx

4. Finally, you will need to set the path of the ‘includes’ library, so to do this, go to Project -> properties -> C/C++ general -> Paths and Symbols, then click on the ‘Includes Tab (first one), and under languages go to GNU C++, then click on the ‘Add…’ button the right, and then select the folder C:\MinGW\include, and press enter.

Done!

Tags: , , , , , , , , ,