blog

How I converted my VR game into an AR game

Introduction

I recently talked about my experience of developing a VR Space exploration game. The original game was developed for Oculus Quest using Unity Engine. In this post, I will show how I converted my Virtual Reality game into an Augmented Reality game using Unity and Vuforia.

Objective and Storyline

Similar to my previous game, this game too is about space exploration. The game has a main menu that allows users to select between “Build” and “Play” mode. In the Build mode, users can add multiple greenhouses, spaceships and planets. In this mode, the user had full control over the placement, orientation and motion of the 3D objects. In the Game mode the user cannot change these orientations, however the user can switch between day mode and night mode. The user can also place the cargos dropped by spaceships anywhere in the plane.

Video Walkthrough

Setting up the scene

By default, the users see the Main Menu that consists of two buttons:

  1. Build Menu
  2. Play Menu

Along with this, my scene has a grey plane to give users an illusion of a virtual ground. This grey plane is anchored to an image target.

Build Menu

The build menu contains four buttons:

  1. Spaceship – to add/remove spaceships
  2. Planets – to add/remove planets
  3. Greenhouse – to add/remove greenhouses
  4. Home – to go back to Main Menu

Adding Greenhouses

Clicking on the GreenHouse icon multiple times leads to different actions. Same icon was overloaded with multiple actions for the sake of brevity while being as intuitive as multiple buttons.

Greenhouse button behavior:

  • First click: Greenhouse One is spawned
  • Second click: Greenhouse Two is spawned
  • Third click: Both Greenhouses are removed from the scene
  • Repeat

Adding Planets

Same approach as above is used to add planets. Users can click on the Planets button multiple times to add/remove planets from the scene.

Adding Spaceships

The game supports two spaceships that can be added removed by the user by tapping the Spaceships button.

Controlling movement and transforming objects

Once the user has added these objects to the scene, they might want to transform the location of these objects, and/or want to add/remove movements from objects like – spaceships and planets.

Users can click on any object and a menu appears to control the location and movement of the object. To guide the user about the selected object, the game also writes the name of the object selected.

Depending upon the object selected, a few options might or might not appear in the control menu. For example, Greenhouses do not have the “Toggle Motion” option as they are stationary. Similarly, as per the assignments guidelines, the spaceship control menu does not have an up-down option to move the object along the Y-axis.

Play Menu

Play menu has only two on-screen buttons:

  1. Home – to go back to the Main Menu 
  2. Day-Night toggle – to switch between day and night mode

Transforming objects in Play Menu:

Users are NOT allowed to transform objects in the Play Menu, with the exception of cargo boxes dropped by the spaceship.

If a user clicks on any object while in the Play Menu, they would not see any transform control panel, like they would have expected inside the Build Menu. 

Moving Cargoes

Users can easily move the cargoes around by simply dragging individual cargoes using their finger.

Day/Night Mode

Using the Day/Night button, users can easily switch between the day mode and the night mode.

In the night mode:

  • The sun disappears
  • The spaceships use flashlights to navigate
  • Lighthouses have lamp posts that lit up.

All the above changes are undone in the Day mode.

Assets used

Following assets were downloaded from the unity asset store for this project:

Standard
blog

I developed my first VR game in less than 10 hours

Introduction

In Spring 2020, I enrolled in CSE 566 Virtual Reality course at Stony Brook University. As an assignment, I had to develop a space exploration VR game for Oculus Quest. Prior to this, I had no experience in game development. In this post, I will talk about my experience of developing a VR game in Unity, and my approach to complete the assignment within 10 hours.

Objective and Storyline

Our game is about space exploration. The game starts with our main character inside a spaceship. The character has to receive a floating cargo from space and navigate to a special planet. Once he has reached near the planet, he should be able to teleport himself to the surface of the planet. On the planet surface, there is a greenhouse. Here the user would be given two tasks which he has to perform. Once complete, the user should be able to teleport himself back to the spaceship.

Video Walkthrough

Codebase and Ethics

Since this project was a part of an assignment for the CSE 566 course at Stony Brook University, I would not be sharing my codebase here. I would however discuss implementations from a broader perspective and share a few basic code gist in order to understand discussed ideas better.

The Setup

Unity and Oculus Setup

For development I used Unity version “2018.4.16f1” on macOS. My hardware was Oculus Quest. 

Start by creating a new project in Unity. Once the project is open, it is important to configure the build setting. We can do this by:

  1. Go to Files and select Build Settings. 
  2. Under platform select Android.
  3. Set Texture Compression to ASTC.

Now, make sure that you have imported the Oculus integration package.

The next step is to add package identification, so Oculus can register your game and display it correctly when deployed. For this:

  1. Go to Edit > Project Settings > Player
  2. Fill Company Name, Product Name and Version.
  3. Under Identification, do the following:
    1. Add Package Name. It must be unique within the Oculus ecosystem. Follow the convention: com.CompanyName.gamename
    2. Add Version and Bundle Version Code.
    3. In Minimum API Level, set the minimum Android version to Android 6.0 Marshmallow (API level 23) for Oculus Quest
    4. In Target API Level, select Automatic (highest installed) 
    5. In Install Location, select Automatic.

Finally, enable VR support by:

  1. Go to Edit > Project Settings.
  2. Select XR Plugin Management, and click Install XR Plugin Management.
  3. Click the Windows tab and select Oculus to install the Oculus XR plugin, which enables the VR support.
  4. Under XR Plugin Management, click Oculus to open and modify the default settings.

Game Development

The setup

We start by first adding a space skybox to our scene. Unity defines skybox as a 6-sided cube that is drawn behind all graphics in the game. Our camera sees the universe from inside this cube therefore giving us the illusion of continuous surrounding space. We can either create our own skybox or import one from Unity’s asset store. For my project, I imported the following asset:

https://assetstore.unity.com/packages/2d/textures-materials/milky-way-skybox-94001

If you deploy the game now, you’ll see vast endless space around. This is good, but not much in itself. Therefore, lets now add more 3D objects like:

  1. Planet Earth: https://assetstore.unity.com/packages/3d/environments/sci-fi/planet-earth-free-23399

  2. Spaceships:
    https://assetstore.unity.com/packages/2d/textures-materials/milky-way-skybox-94001

  3. Other celestial bodies
    https://assetstore.unity.com/packages/3d/environments/sci-fi/vast-outer-space-38913

Once everything is added, place the camera inside the spaceship. At this time, your game should look something like this:

Understanding cameras

A camera, in Unity, is a device to capture and render the space to the player. Depending on the placement of the camera with respect to the player you can define the game’s perspective like – first person or third person. In VR, to make our game more realistic it is better to use a first perspective camera. Thankfully, Oculus’s Unity integration provides such a camera out of the box. You can easily import a VR ready camera from:

Assets/OVR/Prefabs > OVRCameraRig

Using OVRCameraRig would attach the camera to the virtual avatar of the user and would move/rotate as per the user body/head movement in the real world.

Adding physics

We will now introduce physics to our game in order to make it more realistic. Effects like gravity, collision, crash, movement, etc can be achieved using physics. 

Unity Physics is a deterministic rigid body dynamics system and spatial query system written from the ground up using the Unity data-oriented tech stack.

Unity Docs

There are two vital concepts that we need to understand in order to introduce physics in our game – rigidbodies and colliders.

Rigidbodies enable your GameObjects to act under the control of physics. The Rigidbody can receive forces and torque to make your objects move in a realistic way. Any GameObject must contain a Rigidbody to be influenced by gravity, act under added forces via scripting, or interact with other objects through the NVIDIA PhysX physics engine. 

Collider components define the shape of a GameObject for the purposes of physical collisions. A collider, which is invisible, does not need to be the exact same shape as the GameObject’s mesh. A rough approximation of the mesh is often more efficient and indistinguishable in gameplay. The simplest (and least processor-intensive) colliders are primitive collider types. In 3D, these are the Box Collider, Sphere Collider and Capsule Collider. In 2D, you can use the Box Collider 2D and Circle Collider 2D. You can add any number of these to a single GameObject to create compound colliders.

Now that we understand Rigidbody and Collider, let’s add these properties to our planets. Our objective is to enable revolution of planets around the sun. We will first enable Rigidbody property on the planets and then add Sphere Colliders. This ensures that if any planetary body goes off orbit and collides with others, we should be able to observe the correct collision effects.

Adding orbits

We can use Transform.RotateAround to give a simple orbiter path to our planets. For example, the following line of code when added to a planet would make it orbit the sun.

transform.RotateAround (sun.transform.position, Vector3.right, speed * Time.deltaTime);

Switching cameras

We can add multiple cameras to the scene and allow users to switch between them on a button click. This allows users to get a better perspective of the environment. For example, we already have one camera inside the spaceship, let’s add another on top of it. Enable camera toggle via:

   void cameraPositionChange(int camPosition)
   {
       if (camPosition == 1)
       {
           camPosition = 0;
       }
 
       //Set camera position database
       PlayerPrefs.SetInt("CameraPosition", camPosition);
 
       //Set camera position 1
       if (camPosition == 0)
       {
           cameraOne.SetActive(true);
           cameraOneAudioLis.enabled = true;
 
           cameraTwoAudioLis.enabled = false;
           cameraTwo.SetActive(false);
       }
 
       //Set camera position 2
       if (camPosition == 1)
       {
           cameraTwo.SetActive(true);
           cameraTwoAudioLis.enabled = true;
 
           cameraOneAudioLis.enabled = false;
           cameraOne.SetActive(false);
       }
 
   }

Adding gravity inside the spaceship

Remember, our avatar is in the spaceship cockpit. We know that in space there is no gravity, unless artificially created. It would be great if we can allow the user to toggle gravity on and off. In order to see the effects of the gravity, it’s important that we put a few small floating objects in the cockpit. When the gravity is on these objects would fall to the spaceship floor, and when off they would float within.

We start by making our spaceship a rigidbody. This ensures that when the gravity is turned on our floating objects fall and stay on the floor. If we do not make the spaceship a rigidbody, these objects would just pass through the spaceship as if it was unreal. When adding rigidbody to the spaceship, ensure that the ‘Use Gravity’ option is unchecked. 

Now let’s add simple colliders to our floating objects and make them all rigidbodies. Here too we ensure that ‘Use Gravity’ is unchecked by default. The final step is to now toggle ‘Use Gravity’ on button click. We can do that by:

   public Rigidbody rb;
 
   void Update()
   {
       if (OVRInput.GetDown(OVRInput.Button.Two)) {
               rb.useGravity = !rb.useGravity;
       }
   }

Creating a mini-map

A mini-map is a miniature map that is often placed at a screen corner in video games to aid players in orienting themselves within the game world. In our game, we will project a minimap on the cockpit dashboard. This will help users to understand their spaceship’s relative position, thereby enabling them to maneuver the spaceship efficiently to the destination planet.

To create the minimap, we first add a new camera to our scene. Make sure the camera is looking downwards to the spaceship and move it further away on the y-axis so we have a better field of view for the camera. For this camera, set the ‘Projection’ value to ‘Orthographic’. This setting would remove the depth perspective thereby giving a flatter view to the camera. We can also play with ‘Size’ value to get a better field of view.

Once the camera is set up correctly, we now want to project its image on our minimap. For this we will create a ‘RawImage’ UI component. Add this using:

In create, right click > UI >  RawImage

Place this RawImage over the cockpit dashboard, where you want your mini-map to be displayed. Now we want to project our camera view to this raw image. This can be done via a render texture. 

Inside project, right click > Create > Render Texture

This will create a render texture inside the project. We will set the size of the render texture the same as that of the RawImage. We will then set this Render Texture as the target texture for RawImage. The RawImage will now automatically render the overview camera’s feed, thus creating our active minimap.

Maneuvering spaceship

Our spaceship is a rigidbody that can be maneuvered easily using Unity’s transform the position API. 

Teleportation

We can create multiple scenes in the project and allow trigger scene change using a button. This will create an illusion of teleportation.

Conclusion

The complete game development took around 10 hours which included getting started with Unity. The out-of-box physics and interaction APIs provided by the Unity engine is both intuitive as well as easy to use.

Standard
ruby, Ruby on Rails

A formal introduction to gaevents

This post serves a general introduction to gaevents, a Ruby gem to send user events to google analytics.

You can find the gem here:
https://rubygems.org/gems/gaevents

and the code:
https://github.com/singhshivam/gaevents/

What is gaevents?
In a nutshell, gaevents is a Ruby gem that enables sending user events to Google Analytics in batches from a Ruby/Rails application.

What unique problem does it solve?
Traditionally, Google analytics defines events as:

Events are user interactions with content that can be tracked independently from a web page or a screen load.

However, in a complex application, users might trigger delayed events which are equally important for the analytics.

Delayed Events:

To understand delayed events, let’s take the example of Netflix. Netflix allows users to create subscriptions which are then billed monthly or annually depending on the plan. When the user has first created the subscription, they interacted with the application, i.e. navigated a few pages, clicked buttons and submitted forms. These interactions fit perfectly with GA’s definition of “events” and are therefore easy to track. However, depending on your requirement, you might also want to track all subsequent charges that were made on the user’s card. These charges are automatically generated by the system and are not dependent on the user interaction. Such events are referred here as delayed events.

Depending on your application there can be many such system generated events which are equally important for the analytics but don’t fit the textbook definition of events. Gaevents provides a clean way to track these events. The gem also supports batch events update out-of-box!

How does it work?
You can use gaevents to send out the events as and when they occur, however here, we will focus on sending batch updates with the help of redis.

In your application, whenever an event is triggered, capture it in a redis queue. Something like:

redis.set("analytical_events", [
   {:event => “event_1”, :user => user1},
   {:event => “event_2”, :user => user2},
   {:event => “event_3”, :user => user3}
]).to_json

You can create a worker job (using DelayedJob or Resque) which will look for these events at a given interval of time:

events = JSON.parse(redis.get("analytical_events"))

Create GAEvents::Event for the collected events:

gaevents = []
events.each { |event|
   gaevents << GAEvents::Event.new({
          :cid => event[:user].cid,
          :t => event[:user].tid,
          :ec => "gauser",
          :ea => event[:event],
          :uid => event[:user].id,
          :tid => event[:user].tid
   })
}

Please refer Measurement Protocol Parameter Reference for the list of all parameters and their accepted values.

Once all the events are collected you can send them in one shot:

res = GAEvents.track(gaevents)

gaevents is focused on solving one unique problem and aims at solving it well.

Please feel free to share your thoughts in the comments below. Do check out the github repository. Any contribution or suggestion is welcome.

Cheers!

Standard
Uncategorized

The Strange Ruby Splat

End of Line

This article has been republished on Monkey and Crow.

As of ruby 1.9, you can do some pretty odd things with array destructuring and splatting. Putting the star before an object invokes the splat operator, which has a variety of effects. First we?ll start with some very useful examples, then we will poke around the dark corners of ruby?s arrays and the splat operator.

Method Definitions

You can use a splat in a method definition to gather up any remaining arguments:

In the example above, what will get the first argument, then *people will capture however many other arguments you pass into say. A real world example of this can be found in the definition of Delegator#method_missing. A common ruby idiom is to pass a hash in as the last argument to a method. Rails defines an array helper Array#extract_options! to make this idiom easier to…

View original post 328 more words

Standard
Immutable JS
immutablejs, Javascript, redux

ImmutableJS Examples For Humans

As I already talked about earlier, we at BlogVault, are redoing our dashboard. We ditched BackboneJS and Underscore templates for flux architecture (Redux) and ReactJS. Redux attempts to make state mutations predictable by imposing certain restrictions on how and when updates can happen. These restrictions are reflected in the three principles of Redux:

  1. Single source of truth
  2.  State is read-only
  3. Changes are made with pure functions

Using ImmutableJS ensures the state is not accidentally mutated, hence strictly following above principles.

Developed and maintained by Facebook, ImmutableJS has a strong community and project itself has 15308 stars and 807 forks on GitHub, at the time of writing. However ImmutableJS currently has one pain point – plain JS examples! If you go through docs, you can find most API examples are in typescript. Understanding or translating this to JS can be difficult for most novice coders. I faced similar issues while getting started. While going through endless SO and GitHub threads I realised I was not alone. In fact I remember seeing a few angry comments, which I do not support, as it goes against the spirit of community. Following this philosophy I decided to note down examples for all APIs for my future reference. This might also help others with similar difficulty.

Most of these examples are basic and should be enough to get started. I have not described any API as its already beautifully done in ImmutableJS docs.

Let me know in comments if I missed anything or made any errors.


List()
var list = Immutable.List([1,2,3])
// [1, 2, 3]
List.isList()
Immutable.List.isList(list)
// true
List.of()
var list = Immutable.List.of(1,2,3);
// [1, 2, 3]
list.size
// 3
set()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
newlist = list.set(0, "new value");
console.log(list.toJS());
// [1, 2, 3]
console.log(newlist.toJS());
// ["new value", 2, 3]
delete() – alias remove
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
newlist = list.delete(0);
console.log(list.toJS());
// [1, 2, 3]
console.log(newlist.toJS());
// [2, 3]
insert()
var list = Immutable.List.of(1,2,3);
var newlist = list.insert(1, 'bar');
console.log(list.toJS());
// [1, 2, 3]
console.log(newlist.toJS());
// [1, "bar", 2, 3]
clear()
var list = Immutable.List.of(1,2,3);
list = list.clear();
console.log(list.toJS());
// []
push()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
list = list.push('bar');
console.log(list.toJS());
// [1, 2, 3, 'bar']
pop()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
list = list.pop();
console.log(list.toJS());
// [1, 2]
unshift()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
list = list.unshift('bar');
console.log(list.toJS());
// ['bar', 1, 2, 3]
shift()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
list = list.shift();
console.log(list.toJS());
// [2, 3]
update()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
list = list.update(1, function(){ return 5 });
console.log(list.toJS());
// [1, 5, 3]
merge()
var list = Immutable.List.of(1,2,3);
var newlist = Immutable.List([4,5]);
console.log(list.toJS());
// [1, 2, 3]
list = list.merge(newlist);
console.log(list.toJS());
// [4, 5, 3]
mergeWith()
var list = Immutable.List.of(1,2,3);
var newlist = Immutable.List([4,5]);
console.log(list.toJS());
// [1, 2, 3]
list = list.mergeWith((prev, next) => prev + next, newlist);
console.log(list.toJS());
// [5, 7, 3]
mergeDeep()
var list = Immutable.List.of(1,2,3);
var newlist = Immutable.List([4,5]);
console.log(list.toJS());
// [1, 2, 3]
list = list.mergeDeep(newlist);
console.log(list.toJS());
// [4, 5, 3]
mergeDeepWith()
var list = Immutable.List.of(1,2,3);
var newlist = Immutable.List([4,5]);
console.log(list.toJS());
// [1, 2, 3]
list = list.mergeDeepWith((prev, next) => prev + next, newlist);
console.log(list.toJS());
// [5, 7, 3]
setSize()
var list = Immutable.List.of(1,2,3);
console.log(list.toJS());
// [1, 2, 3]
list = list.setSize(5);
console.log(list.toJS());
// [1, 2, 3, undefined, undefined]
list = list.setSize(2);
console.log(list.toJS());
// [1, 2]
setIn()
var list = Immutable.fromJS([1,['foo','bar'],3,4,5,6]);
console.log(list.toJS());
// [1, ['foo','bar'], 3, 4, 5, 6]
list = list.setIn([1, 0], 'new') ;
console.log(list.toJS());
// [1, ['new','bar'], 3, 4, 5, 6]
deleteIn()
var list = Immutable.fromJS([1,['foo','bar'],3,4,5,6]);
console.log(list.toJS());
// [1, ['foo','bar'], 3, 4, 5, 6]
list = list.deleteIn([1, 0]) ;
console.log(list.toJS());
// [1, ['bar'], 3, 4, 5, 6]
updateIn()
var list = Immutable.fromJS([1,['foo','bar'],3,4,5,6]);
console.log(list.toJS());
// [1, ['foo', 'bar'], 3, 4, 5, 6]
list = list.updateIn([1, 0], val => 'new ' + val) ;
console.log(list.toJS());
// [1, ['new foo', 'bar'], 3, 4, 5, 6]
mergeIn()
var list = Immutable.fromJS([1,['foo','bar'],3,4,5,6]);
var newlist = Immutable.fromJS(['a']);
console.log(list.toJS());
// [1, ['foo', 'bar'], 3, 4, 5, 6]
list = list.mergeIn([1], newlist) ;
console.log(list.toJS());
// [1, ['a', 'bar'], 3, 4, 5, 6]
mergeDeepIn()
var list = Immutable.fromJS([1,['foo','bar'],3,4,5,6]);
var newlist = Immutable.fromJS(['a']);
console.log(list.toJS());
// [1, ['foo', 'bar'], 3, 4, 5, 6]
list = list.mergeDeepIn([1], newlist) ;
console.log(list.toJS());
// [1, ['a', 'bar'], 3, 4, 5, 6]
withMutaions()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.withMutations(map => {
map.push('bar').set(0, 'foo');
});
console.log(list.toJS());
// ["foo", 2, 3, 4, 5, 6, "bar"]
asMutable()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.asMutable().map((item) => {
return item * item
});
console.log(list.toJS());
// [1, 4, 9, 16, 25, 36]
asImmutable()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.asImmutable().map((item) => {
return item * item
});
console.log(list.toJS());
// [1, 4, 9, 16, 25, 36]
toSeq()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.toSeq();
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
toKeyedSeq()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.toKeyedSeq();
console.log(list.toJS());
// {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6}
toIndexedSeq()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.toIndexedSeq();
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
toSetSeq()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list = list.toSetSeq();
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
fromEntrySeq()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
list.fromEntrySeq();
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
equals()
var list = Immutable.fromJS([1,2,3,4,5,6]);
var list2 = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.equals(list2))
// true
hashCode()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.hashCode());
// 1012924004
get()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
console.log(list.get(5));
// 6
has()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toJS());
// [1, 2, 3, 4, 5, 6]
console.log(list.has(5));
// true
console.log(list.has(12));
// false
includes()
var list = Immutable.fromJS([1,'foo',3,4,5,6]);
console.log(list.toJS());
// [1,'foo',3,4,5,6]
console.log(list.includes('foo'));
// true
console.log(list.includes('bar'));
// false
first()
var list = Immutable.fromJS([1,'foo',3,4,5,6]);
console.log(list.toJS());
// [1,'foo',3,4,5,6]
console.log(list.first());
// 1
last()
var list = Immutable.fromJS([1,'foo',3,4,5,6]);
console.log(list.toJS());
// [1,'foo',3,4,5,6]
console.log(list.last());
// 6
getIn()
var list = Immutable.fromJS([1,['foo', 'bar'],3,4,5,6]);
console.log(list.toJS());
// [1,['foo', 'bar'],3,4,5,6]
console.log(list.getIn([1,0]));
// foo
hasIn()
var list = Immutable.fromJS([1,['foo', 'bar'],3,4,5,6]);
console.log(list.toJS());
// [1,['foo', 'bar'],3,4,5,6]
console.log(list.hasIn([1,0]));
// true
console.log(list.hasIn([1,1,1]));
// false
toJS()
var list = Immutable.fromJS([1,['foo', 'bar'],3,4,5,6]);
console.log(list.toJS());
// [1,['foo', 'bar'],3,4,5,6]
toArray()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toArray());
// [1, 2, 3, 4, 5, 6]
toObject()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toObject());
// {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6}
toMap()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toMap());
// Immutable map
toOrderedMap()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toOrderedMap());
// Ordered Immutable Map
toSet()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toSet());
// returns set
toOrderedSet()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toOrderedSet());
// returns ordered set
toList()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toList());
// list
toStack()
var list = Immutable.fromJS([1,2,3,4,5,6]);
console.log(list.toStack());
// stack
keys()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.keySeq().toArray());
// [0, 1, 2, 3, 4, 5]
values()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.valueSeq().toArray());
// ["one", "two", "three", "four", "five", "six"]
entry()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.entrySeq().toArray());
// { 0: [0, "one"], 1: [1, "two"], 2: [2, "three"], 3: [3, "four"], 4: [4: "five"], 5: [5: "six"] }
map()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
list.map(function (k, v) {
console.log('—');
console.log(k);
console.log(v);
});
// —
// one
// 0
// —
// two
// 1
// —
// three
// 2
// —
// four
// 3
// —
// five
// 4
// —
// six
// 5
filter()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
var result = list.filter(function (k, v) {
return v % 2 == 0
});
console.log(result.toJS());
// ["one", "three", "five"]
filterNot()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
var result = list.filterNot(function (k, v) {
return v % 2 == 0
});
console.log(result.toJS());
// ["two", "four", "six"]
reverse()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.reverse().toJS());
// ["six", "five", "four", "three", "two", "one"]
sort()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.sort().toJS());
// ["five", "four", "one", "six", "three", "two"]
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.sort((a, b) => b – a).toJS());
// [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
sortBy()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.sortBy(v => v % 3).toJS());
// [3, 6, 9, 1, 4, 7, 10, 2, 5, 8]
groupBy()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.groupBy(x => x % 2).toJS());
// [[2,4,6,8,10], [1,3,5,7,9]]
forEach()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
list.forEach(function(key) { console.log(key); });
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
slice()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.slice(3, -3).toJS());
// [4, 5, 6, 7]
rest()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.rest().toJS());
// [2, 3, 4, 5, 6, 7, 8, 9, 10]
butLast()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.butLast().toJS());
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
skip()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.skip(2).toJS());
// [3, 4, 5, 6, 7, 8, 9, 10]
skipLast()
var list = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.skipLast(2).toJS());
// [1, 2, 3, 4, 5, 6, 7, 8]
skipWhile()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.skipWhile(x => x.match(/o/)).toJS());
// ["three", "four", "five", "six"]
skipUntil()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.skipUntil(x => x.match(/f/)).toJS());
// ["four", "five", "six"]
take()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.take(2).toJS());
// ["one", "two"]
takeLast()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.takeLast(2).toJS());
// ["five", "six"]
takeWhile()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.takeWhile(x => x.match(/o/)).toJS());
// ["one", "two", undefined, "four"]
takeUntil()
var list = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list.takeUntil(x => x.match(/f/)).toJS());
// ["one", "two", "three"]
concat()
var list1 = Immutable.List([ 1,2,3,4,5,6,7,8,9,10 ]);
var list2 = Immutable.List([ 'one', 'two', 'three', 'four', 'five', 'six' ]);
console.log(list1.concat(list2).toJS());
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "one", "two", "three", "four", "five", "six"]
flatten()
var list = Immutable.fromJS([ 1,2, [3,4,5,6] ,7,8,9,10 ]);
console.log(list.flatten().toJS());
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
flatMap()
var list = Immutable.fromJS([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.flatMap(v => [v, v * 2]).toJS());
// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18, 10, 20]
interpose()
var list = Immutable.fromJS([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.interpose(0).toJS());
// [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10]
interleave()
var list = Immutable.fromJS([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.interleave(Immutable.Seq.of('A','B','C','D','E','F','G')).toJS());
// [1, "A", 2, "B", 3, "C", 4, "D", 5, "E", 6, "F", 7, "G"]
splice()
var list = Immutable.fromJS([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.splice(2,5).toJS());
// [1, 2, 8, 9, 10]
zip()
var list = Immutable.fromJS([ 1,2,3,4,5,6 ]);
console.log(list.zip(Immutable.Seq.of('one', 'two', 'three', 'four', 'five', 'six')).toJS());
// [[1, "one"], [2, "two"], [3, "three"], [4, "four"], [5, "five"], [6, "six"]]
zipWith()
var list = Immutable.fromJS([ 1,2,3 ]);
console.log(list.zipWith(function () { return Immutable.List(arguments); }, Immutable.Seq.of(4,5,6), Immutable.Seq.of(7,8,9)).toJS());
// [[1,4,7], [2,5,8], [3,6,9]]
reduce()
var list = Immutable.fromJS([ 1,2,3,4,5,6,7,8,9,10 ]);
console.log(list.reduce((a, b) => a + b, 0));
// 55
reduceRight()
var list = Immutable.fromJS([ 'a', 'b', 'c' ]);
console.log(list.reduceRight((a, b) => a + b));
// cba
every()
var list = Immutable.fromJS([ 5,6,7 ]);
console.log(list.every(v => v > 4));
// true
console.log(list.every(v => v > 6));
// false
some()
var list = Immutable.fromJS([ 5,6,7 ]);
console.log(list.some(v => v < 4));
// false
console.log(list.some(v => v > 6));
// true
join()
var list = Immutable.fromJS([ 5,6,7 ]);
console.log(list.join(' – '));
// 5 – 6 – 7
isEmpty()
var list1 = Immutable.fromJS([ 5,6,7 ]);
var list2 = Immutable.fromJS([]);
console.log(list1.isEmpty());
// false
console.log(list2.isEmpty());
// true
count()
var list = Immutable.fromJS([ 5,6,7 ]);
console.log(list.count());
// 3
countBy()
var list = Immutable.fromJS([ 5,6,7 ]);
console.log(list.countBy(x => x % 2).toJS());
// {0: 1, 1: 2}
find()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.find(x => x % 2 == 0));
// 6
findLast()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.findLast(x => x % 2 == 0));
// 8
findEntry()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.findEntry(x => x % 2 == 0));
// [1, 6]
findLastEntry()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.findLastEntry(x => x % 2 == 0));
// [3, 8]
findKey()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.findKey(x => x % 2 == 0));
// 1
findLastKey()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.findLastKey(x => x % 2 == 0));
// 3
keyOf()
var list = Immutable.fromJS([ 5,6,7,8,9,7 ]);
console.log(list.keyOf(7));
// 2
lastKeyOf()
var list = Immutable.fromJS([ 5,6,7,8,9,7 ]);
console.log(list.lastKeyOf(7));
// 5
max()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.max(x => x % 2 == 0));
// 8
maxBy()
var list = Immutable.Seq([
{ name: 'Oakley', age: 7 },
{ name: 'Dakota', age: 7 },
{ name: 'Casey', age: 35 },
{ name: 'Avery', age: 34 },
]);
console.log(list.maxBy(x => x.age));
// {name: "Casey", age: 35}
min()
var list = Immutable.fromJS([ 5,6,7,8,9 ]);
console.log(list.min());
// 5
minBy()
var list = Immutable.Seq([
{ name: 'Oakley', age: 7 },
{ name: 'Dakota', age: 5 },
{ name: 'Casey', age: 35 },
{ name: 'Avery', age: 34 },
]);
console.log(list.minBy(x => x.age));
// {name: "Casey", age: 35}
indexOf()
var list = Immutable.fromJS([ 5,6,7,8,9,7 ]);
console.log(list.indexOf(7));
// 2
lastIndexOf()
var list = Immutable.fromJS([ 5,6,7,8,9,7 ]);
console.log(list.lastIndexOf(7));
// 5
findIndex()
var list = Immutable.fromJS([ 5,6,7,8,9,7 ]);
console.log(list.findIndex(x => x % 2 == 0 ));
// 1
findLastIndex()
var list = Immutable.fromJS([ 5,6,7,8,9,7 ]);
console.log(list.findLastIndex(x => x % 2 == 0 ));
// 3
isSubset()
var list1 = Immutable.Map({a:1, b:1});
var list2 = Immutable.Map({a:1, b:1, c:3});
console.log(list1.isSubset(list2));
// true
console.log(list2.isSubset(list1));
// false
isSuperset()
var list1 = Immutable.Map({a:1, b:1});
var list2 = Immutable.Map({a:1, b:1, c:3});
console.log(list1.isSuperset(list2));
// false
console.log(list2.isSuperset(list1));
// true

Standard
performance

How I reduced my blogspot page load time by half

Page load time is serious business. Okay may not be for my old PhotoShop blog which I no longer maintain, but for your main-source-of-income site it is! In 2012 Amazon analyzed its data and calculated that a page load slowdown of just one second could cost it $1.6 billion in sales each year. That’s massive, in fact let me help you visualize that amount – Facebook bought Instagram for $1 billion same year. You can do your math now!

Anyway coming back to reality, I have this old blog that I used to maintain in my freshman year. It was terribly built over blogspot. I copy pasted some theme, bundled a bunch of widgets and marketed extensively among my peer which lead to some good traffic. That improved my google rank especially for one particular post on Godfather style poster designing.

Fast forward today, I accidentally visited my old blog and realized it was still getting consistent traffic. That was great! However first thing I noticed about my own blog was – how shitty it was! I checked my browser console only to confirm my blog was bleeding with javascript errors. So much so, even posts date were displayed as “undefined”.

Next thing I noticed was the painful load time. I felt like running out of patience with my own blog owing its terrible load speed. My blog had one share widget that would take forever to load. Then there were links that were not pointing to anywhere. Sadly I had no one to blame and I didn’t feel very proud of myself.

I would have left it on its state as I have no intentions of contributing there, however there is something every emotional about your first blog. Also the developer in me could not tolerate such mess of code and hence I decided to get my hands dirty cleaning it.

Say no to JavaScript errors

Here is how my browser console looked initially on page load:
Selection_049

That’s ugly. There are a lot of stupid errors that can easily be solved. As clearly visible from above screenshot my theme was trying to load some amazon affiliate link. An adware? maybe! after all I copy pasted theme code from some untrusted source. First thing was to remove any code I cannot understand . This was a time taking task but result was worth it. It took care of all javascript errors and cleaned my blog from all adwares and unwanted backlinks.

Widgets should not slow you down

I noticed my share widget would just take forever to load. An ideal solution would have been to fix it or replace it with a better light-weight share widget, however I went brutal here and chopped it off completely from my site. One less thing to worry about!

Bare minimum navigation

As mentioned above my blog had nav menus pointing no where. That was bad design, confusing and hence completely unacceptable. Fix – remove them or replace them with more suited menus.

Here’s how it looked initially:

Selection_052

“Post RSS” and “Comments RSS” are of least importance and surely does not deserve a place in top menu. “Edit”? Now seriously, how did it even get there? It was plane stupid. I removed all these three menus and replaced them with “About me” which link to About page of this blog.

UI glitches are disgrace

My posts were not able to show post date correctly, instead it would print undefined:

Selection_051

I looked into the theme code, the issue here was, the original author made an assumption about the date format returned upon query. Obviously his assumption was wrong and hence his clever attempt of parsing the result resulted “undefined” . If years of coding has taught me one thing, its say no to assumptions. I simplified the code and completely removed the parsing part to display simple date.

Say yes to page-breaks

All these changes did very little to improve my page load time since my home page was still fetching a lot of data. This made me realize my posts had no page breaks.  Just for sake of clarifying: A page break is a marker in an electronic document that tells the document interpreter that the content which follows is part of a newpage. Or in simpler words enabling “read more…” option. This reduced my homepage size to a great extent as now posts only have a feature image and all other images go on their individual page and hence are not fetched in home page.

Results

That was a lot of work on a blog you don’t even maintain. But at the end I was rewarded with amazing result. Lets see:

Pingdom test result before my changes:

Selection_033

Pingdom test after my changes:

Selection_037

As claimed before, page load time reduced by half! And obviously you can see improvements in other areas too. Yoo…hoo!! 🙂

Standard
Javascript, react, redux

My Experience with React and Redux

How it started

We, at BlogVault, decided to completely redo our web application UI, which is currently powered by Backbone.js with Underscore templates. Exploring options, we tried using MarionetteJs on top of Backbone.js for our specialized migration dashboard that powers migration for our partner web-hosts like wpengine, savvii, cloudways etc. While MarionetteJs provided a decent improvement over our Backbone.js code with its common-practice architectural solutions, the code still looked hacky at times.

In Backbone.js responsive views listen to models and collections and re-render once underlying data is updated. However Backbone.js being so minimal (which is often credited as a plus point), it leaves most design completely on developers. This is where the problem starts, if you are not a disciplined coder there are enough ways to screw up. For example – manipulating DOM directly upon success callback. I have seen enough people posting such code on various forums. This may not be a big issue at beginning, but as the application keeps growing and you keep adding new features, you realize your views are not in perfect sync with your models and collections anymore. A quick fix would be manually manipulating DOM to update UI, which as insane as it sounds, is not at all a rare practice, such code snippets are posted all over the internet in abundance. This was just one example, there are many other. This leads to spaghetti data-flow, abrupt DOM manipulations, and at times massive memory leaks. This was one of the big reason we wanted to move away from Backbone.js.

Next we considered AngularJs, however dropped it almost immediately after we learned that Angular 2.0 (which at that time was not released and currently is in beta) won’t be backward compatible.

Finally we decided to try Facebook’s newly released view library React and application architecture Flux. Rewriting everything in React and Flux had its own risks. React was brand new, meaning considerably smaller community, lesser plugins and most terrifying – fewer StackOverflow posts! Also most of the code is in ECMA6, and to add further,  Flux is a non-MVC (or MV*?) architecture. However experimenting with few examples we decided to give it a try.

 

What is React and Redux?

The official site for React defines it as “a javascript library for building user interfaces”. And Redux is officially defined as “a predictable state container for JavaScript apps”. Lets look at them in detail.

Redux can easily be distinguished with most of the object-oriented MV* architectures, as:

  • the complete state of your application is maintained inside a single object called store.
  • at any given time the App’s state (store) is immutable, and
  • data flows strictly in one direction.

That’s a lot to digest if you are new to this. However the more we dive into the real world problems, more it makes sense.

 

How they work?

Data in a Flux architecture flows in single direction:

Action > Dispatcher > Store > View

 

Action suggests something just happened. Dispatcher is called and it sends the action to the store. Store modifies itself (without mutating existing structure) in response to action. Finally, as per the state of store, view gets updated.

Redux is an extremely light implementation of Flux architecture. It implements the above Flux data-flow in following sequence:

Action > Dispatch > Reducer > Store

 

In Redux implementation, an action is a plain object describing what happened. A function store.dispatch(action) is called to pass action to store. By this time, Redux knows something happened and depending on action, it has the result for what happened (suppose as action triggered a server request and got response). Now, in reducer we specify how the store’s state should change in response to that action. Once the reducer modifies the state, React picks up the new store and re-renders view automatically.

 

Now coming back to React. As it should be clear by now, React is the view part of our implementation. If I have to explain it in the vaguest possible way, I can say its comprises of two parts:

  • a template written in jsx.
  • a mechanism to maintain its own internal state in memory.

At the end React processes these two parts and churns out good-old-plain HTML that your browser understands.

Given the capability of maintaining states, it makes React extremely powerful and a delight to write UI on. Think of this – you need to display a message based on some event. Generally you will do DOM manipulation in event handler. However in React all you need to do is set a state in event handler and as per your template, React will automatically re-render that particular part. That’s powerful, and clean!

In fact I recently read somewhere someone comparing DOM manipulation with goto statements. Its as bad! There is no definitive source of truth and hence tracking down the source of manipulation is walking into hell-hole.

 

Conclusion

React and Redux together are fairly powerful and provides robust and efficient solution for building a single page application. In Redux, since the data-flow is restricted to one direction, scope for screwing up is significantly reduced. React has beautiful in-built data-binding which responds to state changes flawlessly. And lastly React provided various components lifecycle callbacks which helps write elegant easy-to-maintain code.

It was difficult learning curve attributed to – relatively fewer resources, smaller (yet massively growing) community, ECMA6 based javascript (which was completely new to me), new concepts like virtual DOM etc. However once I got the basics clear, everything seem to fall in line. 🙂

Standard
linux, Mariadb, mysql, Ubuntu

How I screwed MySQL install with MariaDB and recovered

Broken packages are mess! I recently installed MariaDB to give it a try. After testing, I decided to uninstall it for now and maybe come back later. I was careless while removing MariaDB and ended up messing MySQL configs (MariaDB runs on top of MySQL). Things were only to get worse from here. A high priority task pops up that requires me to access MySQL. Unable to access it, I decide to completely remove MySQL and do a fresh install – basically a hard reset. If only things were that simple in real world. By this time my MariaDB was half removed, MySQL configs were a mess and I was now about to remove MySQL completely. Here’s what happened:


root@bluegene:/etc/apt# apt-get remove mysql-server-5.6
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following packages will be REMOVED:
mysql-server-5.6
0 upgraded, 0 newly installed, 1 to remove and 19 not upgraded.
1 not fully installed or removed.
After this operation, 52.7 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database … 399494 files and directories currently installed.)
Removing mysql-server-5.6 (5.6.27-0ubuntu0.15.04.1) …
/var/lib/dpkg/info/mysql-server-5.6.postrm: line 53: /usr/share/mysql-common/configure-symlinks: No such file or directory
dpkg: error processing package mysql-server-5.6 (–remove):
subprocess installed post-removal script returned error exit status 1
Errors were encountered while processing:
mysql-server-5.6
E: Sub-process /usr/bin/dpkg returned an error code (1)

Alright, maybe I did not uninstall MariaDB correctly. Lets try removing that once more:


root@bluegene:/etc/apt# apt-get remove mariadb-server
Reading package lists… Done
Building dependency tree
Reading state information… Done
Package 'mariadb-server' is not installed, so not removed
The following packages will be REMOVED:
mysql-server-5.6
0 upgraded, 0 newly installed, 1 to remove and 19 not upgraded.
1 not fully installed or removed.
After this operation, 52.7 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database … 399494 files and directories currently installed.)
Removing mysql-server-5.6 (5.6.27-0ubuntu0.15.04.1) …
/var/lib/dpkg/info/mysql-server-5.6.postrm: line 53: /usr/share/mysql-common/configure-symlinks: No such file or directory
dpkg: error processing package mysql-server-5.6 (–remove):
subprocess installed post-removal script returned error exit status 1
Errors were encountered while processing:
mysql-server-5.6
E: Sub-process /usr/bin/dpkg returned an error code (1)

Same error! Ok, I clearly screwed MySQL. I should try installing it back. Lets see how that goes:


root@bluegene:/etc/apt# apt-get install mysql-server
Reading package lists… Done
Building dependency tree
Reading state information… Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:
The following packages have unmet dependencies:
mysql-server : Depends: mysql-server-5.6 but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

Unmet dependencies? Ok! I know what to do in such cases:


root@bluegene:/etc/apt# sudo apt-get -f install
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following packages will be REMOVED:
mysql-server-5.6
0 upgraded, 0 newly installed, 1 to remove and 19 not upgraded.
1 not fully installed or removed.
After this operation, 52.7 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database … 399494 files and directories currently installed.)
Removing mysql-server-5.6 (5.6.27-0ubuntu0.15.04.1) …
/var/lib/dpkg/info/mysql-server-5.6.postrm: line 53: /usr/share/mysql-common/configure-symlinks: No such file or directory
dpkg: error processing package mysql-server-5.6 (–remove):
subprocess installed post-removal script returned error exit status 1
Errors were encountered while processing:
mysql-server-5.6
E: Sub-process /usr/bin/dpkg returned an error code (1)
root@bluegene:/etc/apt# sudo dpkg –configure -a
root@bluegene:/etc/apt# sudo apt-get -f install
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following packages will be REMOVED:
mysql-server-5.6
0 upgraded, 0 newly installed, 1 to remove and 19 not upgraded.
1 not fully installed or removed.
After this operation, 52.7 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database … 399494 files and directories currently installed.)
Removing mysql-server-5.6 (5.6.27-0ubuntu0.15.04.1) …
/var/lib/dpkg/info/mysql-server-5.6.postrm: line 53: /usr/share/mysql-common/configure-symlinks: No such file or directory
dpkg: error processing package mysql-server-5.6 (–remove):
subprocess installed post-removal script returned error exit status 1
Errors were encountered while processing:
mysql-server-5.6
E: Sub-process /usr/bin/dpkg returned an error code (1)

Nothing! That’s scary. There’s no way forward (installing) and there’s no way backward (uninstalling). I am basically stuck!

Maybe autoclean is a good idea? Sadly no difference.

I noticed both MySQL and MariaDB remove commands were exiting because of ‘mysql-server-5.6’, so fixing it was my best bet. I also noticed the error raised while removing mysql-server was from file `/var/lib/dpkg/info/mysql-server-5.6.postrm` as evident in following line:

/var/lib/dpkg/info/mysql-server-5.6.postrm: line 53: /usr/share/mysql-common/configure-symlinks: No such file or directory

dtdm

So what if I comment the line that’s raising this error? Risky, but desperate times – desperate measures. After creating a backup of the file, I edited it to remove the line that raised the error and retried. Here’s what happened :


root@bluegene:/etc/apt# apt-get remove mariadb-server
Reading package lists… Done
Building dependency tree
Reading state information… Done
Package 'mariadb-server' is not installed, so not removed
The following packages will be REMOVED:
mysql-server-5.6
0 upgraded, 0 newly installed, 1 to remove and 19 not upgraded.
1 not fully installed or removed.
After this operation, 52.7 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database … 399494 files and directories currently installed.)
Removing mysql-server-5.6 (5.6.27-0ubuntu0.15.04.1) …
root@bluegene:/etc/apt# apt-get remove mariadb-server
Reading package lists… Done
Building dependency tree
Reading state information… Done
Package 'mariadb-server' is not installed, so not removed
0 upgraded, 0 newly installed, 0 to remove and 19 not upgraded.
root@bluegene:/etc/apt# apt-get remove mysql-server
Reading package lists… Done
Building dependency tree
Reading state information… Done
Package 'mysql-server' is not installed, so not removed
0 upgraded, 0 newly installed, 0 to remove and 19 not upgraded.

Finally! Editing the file worked and I was able to remove both packages. Next I fresh installed mysql-server and it worked perfectly. What a relief! 🙂

Standard
ruby

Recover your iPod playlist within seconds

I had to leave for Goa the other day and I was packing my bare essentials when I came across my age old forgotten iPod. Finding it out of blue was a bliss and I decided to take it along. I put it on charge and it was ready to rock.

2015-08-30I never realized what wonder old playlists can do. Listening to those old tracks I felt as if I was transported back to those good old carefree college days. After returning from Goa I decided to export those tracks to my computer, however there was an issue. We all know for some reason Apple renames music files and rearrange them in random folders. This makes it impossible to figure out which file corresponds which track.

Here take a look:

ipod files list

These are all random filenames. However to my relief these files were not encrypted and their ID3 tags were still intact. That meant all I needed to do was rename these files and I was good to go.

However given the size of my playlist (6.5 GB) there was no option to do this manually. So I wrote a little script that could help me out.

Selection_006

My script goes through these files, collecting their ID3 tags, maintaining a hash and finally copying these files over user provided destination to respective folders based on album name and the file itself is renamed on track title. Running the script restored back my playlist within 105 seconds. Here’s the benchmark:

0.160000 7.470000 7.630000 (105.228952)

And this is how my playlist looks now on my file system:

Selection_007 Selection_008

Here is the source code:


require "id3tag"
require "fileutils"
puts "enter absolute path to music folder:"
indir = gets.chomp
# Example: "/home/shivam/Music/Music/F01"
indir = indir.sub(/\/$/, "") + "/*"
puts "enter extraction path (absolute):"
outdir = gets.chomp
# Example: "/tmp/songs"
outdir = outdir.sub(/\/$/, "") + "/"
files = Dir[indir]
files.reject! { |file| file !~ /.mp3/ }
meta_array = []
files.each { |file|
hash = {}
ID3Tag.read(File.open(file, "rb")) do |tag|
hash[:artist] = tag.artist
hash[:title] = tag.title
hash[:album] = tag.album
hash[:path] = file
end
meta_array << hash
}
albums = meta_array.group_by { |a| a[:album] }
begin
albums.each { |album|
album_path = outdir + album[0].gsub(/\//,"-")
FileUtils.mkdir_p album_path
album.last.each { |hash|
title = (hash[:title] || "Unknown Track #{rand(1000)}").gsub(/\//,"-")
FileUtils.cp hash[:path], (album_path + "/" + title).sub(/\.mp3$/,"") + ".mp3"
}
}
end
rescue => e
puts e.inspect
puts @hash.inspect
end

view raw

mp3edit.rb

hosted with ❤ by GitHub

Feel free to star, fork, follow or contribute on GitHub. 🙂

Standard
plugin, wordpress

Announcing Release of “The Video Popup” plugin at WordPress Repository

My plugin “The Video Popup” got approved and is now available for download in wordpress repository. Its a light-weight plugin that generates a YouTube video popup when a page is scrolled to the bottom. You can check it out here:

https://wordpress.org/plugins/the-video-popup/

The next version of the plugin is expected to have:

  • support for vimeo
  • custom point of trigger
  • overlay video popup

Feel free to suggest more features in comments below or rate the plugin in the repository. 😉

Standard