Wednesday, 31 October 2018

Hacktoberfest Summary

Issues
Pull Requests
  1. pull-1
  2. pull-2 pull that resulted in pull-2
  3. pull-3
  4. pull-4
  5. pull-5
Posts
  1. post-1
  2. post-2
  3. post-3
  4. post-4
  5. post-5
This month I made 5 contributions to open source projects:
  1. 1 contribution to algorithms game
  2. 1 bug fix in filer
  3. 2 contributions to consumable algorithms library (biggest contributions)
  4. 1 contribution to a small guess number game
During October I learned in practice how to use GitHub, how to create pull requests, how to resolve conflicts in pull requests. That's, I learned how Open Source works.

I added 441 lines of code and removed 12 lines. Each pull request includes changes to code (no README spell checking, sorting, and so on).

What I like in Open Source


1. I can choose any project I like and work on it
2. Experienced programmers might help me

What I don't like in Open Source


1. It's hard to contribute to a big project because you have to learn a lot of code written in unfamiliar style (That's why I was happy to find consumable algorithms library. I didn't have to learn existing code, my code didn't interact with existing code)
2. In many projects (usually small projects) response time is a few weeks

I also was disappointed by the fact that most people are not trying to do something helpful, something that will really improve project. Instead, they just want to get a PR without coding.

Conclusion


In general, Hacktoberfest is a good idea: during October a lot of people contribute to open source projects, some of them might continue contributing after the end of Hacktoberfest. However, most people contribute with minor and often senseless changes and stop contributing after Hacktoberfest.

Next time in order to increase efficiency I will contribute a lot to one project instead of contributing to many projects.

Tuesday, 30 October 2018

Hacktoberfest Fifth Pull Request

For my last pull request I again contributed to consumable algorithms library (yes, I like Math and algorithms). This time I chose Euler's Totient Function.
Euler's Totient Function counts the positive integers up to a given integer n that are relatively prime to n (relatively prime numbers are numbers that have only one common divisor - 1).

This is how Euler's function looks like:

The solution of the problem is reduced to one formula:
f(n) = (P1^B1 - P1^(B1 - 1))*(P2^B2 - P2^(B2 - 1)).....*(Pm^Bm - Pm^(Bm - 1)), where P are prime divisors of n and B are powers of divisors.

That's, to find f(n) we need

  • to find prime divisors of n and powers of divisors
  • to write fast power function
  • for fast power function we need to write Bitset class
You can see all code with JSDocs comments here.

Hacktoberfest Fourth Pull Request

For my fourth pull request I choose small project. It's a guess number game: user should guess a number in given range. When user types wrong number, he gets hints.
Try it

What I did

I tried playing this game and didn't like how "Show Hints" slider works. So, I decided to change it.
Before changes slider changed his state in the following case:

  • you clicked and released button inside slider
After changes:

  • you clicked inside slider and released button in the same coordinate
  • or you clicked inside slider, moved mouse to the correct side and released button
That's, for exampe, if slider is inactive, you click on it, move mouse to the left, and release button, slider will not change its state
Now, slider behaves like real slider (pull request is not merged yet)

This slider is using a Bootstrap class that defines its design and behaviour. The problem was that I did not want to change its design, so I did not remove a Bootstrap class. And because I didn't remove a Bootstrap class, I did not cancel its behaviour. That's, I had to write code "above that class" (default behaviour + my code = desired behaviour).

Links

Hacktoberfest Third Pull Request

This week I contributed to consumable algorithms library by creating the most complex and biggest pull request so far - Convex Hull function.

Convex Hull function


  • receives array of points with (x,y) coordinates
  • returns smallest sorted array of points that belong to smallest convex hull of received points
  • sorted array means that array[i] and array[i+1] are adjacent vertices of a hull (array[0] and array[array.length-1] are also adjacent
Here is an example of how this function should work:
Points connected by lines are points that are returned by function. As I already mentioned, returned array is sorted, so hull can be easily drawn (by drawing line segments connecting adjacent elements of returned array).

Here are more examples of how convexHull() works:
This is wrong:


This is correct:

Specific cases:

  • If function receives less than 3 points, it returns all points
  • If many points are on one line, only extreme points are returned

Implementation


To solve this problem I had to do a lot of Math and to write 8 functions. You can see full code with JSDocs comments  here. I also added tests for my code. If you want to use this function or any other function from algorithms library, check instructions here in README.md.

Monday, 15 October 2018

Hacktoberfest Second Pull Request

In my second pull request I fixed a bug in Filer.

How I fixed a bug

  1. I was writing a test for rename() when oldPath==newPath (You can see a discussion here). It was expected that function will successfully rename a file, but it failed. We came to the conclusion that function implementation has a bug. Bug was assigned to me and I started working on it.
  2. I went to the implementation file, found rename() and tried to understand how it works.
  3. I found out that find_node() is called and went to it.
  4. In find_node() another function is called, in another function one more function is called, etc. There was a long way to find a mistake, a lot of functions was called. This long process is not interesting to read about, so I will not write about all ifs and function calls.
  5. Finally, check_if_new_file_exists() is called. It has this "if" inside:
if(_(newDirectoryData).has(newname)) { callback(new Errors.EEXIST('newpath resolves to an existing file', newname)); }
If a file with the name we want to rename a file to already exists, callback with an error is called. I removed this if statement and spaces in the else statement that is following this "if". After these changes my test with oldPath==newPath passed (all other tests also passed).

Fixing bugs in your own code is sometimes difficult, even though you know how your code works. But fixing bugs in someone else's code is always more difficult: you have to find out how it works. Different styling and programming techniques slow down debugging. So, I think it would be more rational if a person that wrote a code fixed bugs himself and other people just wrote tests.

Tuesday, 9 October 2018

Hacktoberfest First Pull Request

I contributed to Hacktoberfest game. Here is the list of actions that must be done to take part in the game:

  •  I have asked for this issue, and was assigned it
  •  I have properly filled the "Details" section above arrow_up
  •  I didn't modify any test case red_circle
  •  I have implemented the function and all its tests pass white_check_mark
  •  I have added a new test case for someone to implement new
  •  I have created an issue for my new test case speak_no_evil
  •  I've star the repository (or not, all up to you)
  •  And more importantly, I've had fun! beer

To sum up, you need to solve a problem and to create a new problem that someone else will solve. The idea is that there are always available problems and everyone can start contributing to public repositories.

The Problem I solved

issue-527 pull-567

I wrote a function that takes unknown number of arguments and returns true if it contains any duplicate argument values. Otherwise, returns false (if all arguments are unique).

The algorithm is very simple:

  1. Go through the array of arguments for (let i=0; i<args.length;i++)
  2. For each argument go through the rest of the array for (let j=i+1; j<args.length;j++)
  3. If found the same argument, return true if (args[i] == args[j]) return true;
  4. If did not find any duplicates, return false return false;
Full code:

export const duplicatedArgs = (...args) => {
for (let i = 0; i < args.length; i++)
for (let j = i + 1; j < args.length; j++)
if (args[i] == args[j])
return true;
return false;
};

Problem I suggested

I suggested to write a power function. It is recommended that this function
works faster than O(n).
Here are tests for power():

describe('power', () => {
it('returns 125 for base 5 and power 3', () => {
expect(power(5, 3)).toEqual(125);
});

it('returns -125 for base -5 and power 3', () => {
expect(power(-5, 3)).toEqual(-125);
});

it('returns 1 for base 5 and power 0', () => {
expect(power(5, 0)).toEqual(1);
});

it('returns 5 for base 5 and power 1', () => {
expect(power(5, 1)).toEqual(5);
});

it('returns 1048576 for base 2 and power 20', () => {
expect(power(2, 20)).toEqual(1048576);
});
});

I recommend everyone to take part in this game, because it suits for your
first pull request on Hacktoberfest and it's not hard.
You can also use this game if you need help with some functions: just create
an issue with function description and someone will write it.😊

Friday, 28 September 2018

Release 0.1

I have written a test for fs.rename() when oldPath=newPath.

  1. I started by looking at the list of fs methods in Node.js Documentation and found one (rename) that is clear to me.
  2. After forking filer to my account, I looked at the existing tests and found out that there is no tests for the case when oldPath=newPath.
  3. I wrote a test expecting that a path will be overwritten (as it is stated in Linux Programmer's Manual). By the way, Node.js Docs also state "in the case that newPath already exists, it will be overwritten.
  4. Unfortunately, my test failed. But after numerous experiments and attempts to fix the test, I came to the conclusion that this method might actually work differently.
  5. This is why I rewrote my test in a way that it expects failure in method execution. And it passed.
I still am not sure how rename() should work when oldPath=newPath, but it fails in this case. On the other hand, I learned how to create and run tests for Node.js modules.

Here is a final version of my test:

it('should fail to overwrite an existing file to itself', function (done) {
var fs = util.fs();

fs.open('/myfile', 'w+', function (error, fd) {
if (error) throw error;

fs.close(fd, function (error) {
if (error) throw error;
fs.rename('/myfile', '/myfile', function (error) {
expect(error).to.exist;
expect(error.code).to.equal('EEXIST');
done();
});
});
});
});

I created an issue stating that this test was missing: https://github.com/filerjs/filer/issues/493 and pull request with a test: https://github.com/filerjs/filer/pull/502

I also reveiwed peer's pull request: https://github.com/filerjs/filer/pull/539

describe('fsPromises.Write', function () {
it('should write, read a utf8 file without specifying utf8 in writeFile', function () {
//var fs = util.fs();
//var contents = 'This is a file.';
var fsPromises = util.fs().promises;
return fsPromises.writeFile('/myfile', { encoding: 'utf8' })
.then(() => {
return fsPromises.readFile('/myfile', 'utf8')
.catch((error) => {
expect(error).not.to.exist;
//expect(data).to.equal(contents);
//done();
});
});
});
});

After looking at this test, I went to existing tests and found out that this test already exists. Also, in return fsPromises.writeFile('/myfile' , { encoding: 'utf8' }) data parameter is missing.
I let pull request creator know about my comments.