Thursday, 4 June 2020

Designing an engineering Jugaad




So one fine day we came to know that that the underground water tank is almost empty ! Although we have a fully automated electric pump system which sucks water from underground tank and takes it to water tank on 3rd floor, it acts on water level signal from upper tank, while lower tank is ... "assumed to be filled optimally". But now we came to know that hmm the main input water supply is "not enough" or maybe the input water has not being coming daily ! Yes in undeveloped countries water does not come continuously like electricity. It will come for half hour to two or so hours at any "random time" !

Now the solution to almost empty underground water tank is to use electric motor on main input water supply and fill the underground tank to optimal level. This we need to do not daily but for 2-3 days and after that maybe never based on assumption that the input water supply resumes its mysterious random frequency and flow again !

The problem now is : "How to know when the input water came?". Hmm this needs some sort of water detector. We can purchase some fancy water flow meter and attach it in series to input pipe and measure the signal and attach it to a fancy system like bell. But oh... wait we - the country - is facing a LOCKDOWN ! Hmm so Corona has its name in this story also ! Anyways so the bottom line is : a solution is needed fast and has to be homegrown - cant get any supply from outside.

Can we do without an input water detector ? Yes but then we need to be constantly vigilant of what is happening outside house, we might miss the water tap noise, we might hear it late and hence not solving the water problem. Hmm so looks like we need an engineering solution.

We had a door bell, and some wire. Awesome what if ... a water filled jar can be used to trigger the bell and problem solved ! So after some fidgeting, ripping open some wires and applying tape and bending the two open wire tips and putting an old pencil cell in the old door bell, I experimented with it ... and it worked. As soon as both ends of wire are in water the bell rings... cool. Now a small jar which can collect water from a tap on the water input, as the jar fills the wires conduct and bell rings. Great, one problem solved.

Now when we know what fresh water has come via the bell, which can not be missed as it is loud and catches attention rather quickly. One has to empty the jar which has the alarm wires. Then do some turning and twisting of valves and then apply motor on fresh input water to the underground tank. So far so good. But what happens if input fresh water goes - you see it wont last more than 2 hours or half an hour generally ? In that case motor runs without water and ... this will damage the motor. So problem two : "How to know when the input water has stopped ?"

Hmm to know that water stopped, can we have some way to ring the bell when water stops ? One thing which instantly comes to mind is make a NOR gate and use it to convert an OFF signal into an ON signal which can then ring the bell. Well one may ask how to get a signal when water stops ? One way can be put some conductor which are always immersed in water and when water goes off, then these conductors will STOP conduction or will be in OFF state. Sounds good but I did not want to make this complex, so instead of an electronic NOT gate - I thought why not have a mechanical NOT ? Another disadvantage of electronic NOT would be a voltage would be applied to water and I might have to worry about hydrolysis due to charge !

So how will a mechanical NOT work ? After some pondering I realised it would need some sort of mechanical toggle, when water stops or goes OFF then that should get converted into an ON signal which can then drag a wire which has two open conductors, into a water container.

Hmm sounds reasonable, but how to create the mechanical toggle - upon pondering i realised that a water container with a hole at bottom will empty itself after input water is off. Main property of such a setup is that the weight of this container will decrease drastically after input water supply is off. Hmm so all we need is a sort of pulley system with a heavy but not too heavy weight on the other end. When water supply is on, the container with hole has enough weight to not get pulled up by the weight on other side but when its empty then other side's weight is enough to pull hole container up. This is a mechanical NOT gate ! Gravity is magic :) !

Now the setup is simple - water supply stops, Water leaks from the hole at bottom, its weight decreases, the other side of pulley has a weight and a wire attached to it and gets pulled down. This puts the conducting wire into water and voila the bell rings !!!



Fig. 1

In figure 1 above one can see the small container with a pair of wire going inside. This is what gets pulled in when water supply stops. One can also see the wire connecting to the alarm bell. Also there is a weight (some old metal pipe i used). To solve problem 1 - water on detection - the same small container can also be used to collect water and it will ring the alarm to detect water supply start !


Now see the figure 2 below, this is the mechanical NOT gate aka pulley :


Fig. 2

I had some old pipe, so I made two notches in it for the thread to run along for stability and less friction. Used an old plastic bottle  (one on left) and attached the thread to it. It also has a hole in bottom. See the water is falling in from top. When the water stops is empties itself. Now if you look at thread carefully - on left is plastic bottle with hole and on right is a counter weight, which falls down when left bottle is empty. And when it falls it drags the wire into plastic container two as seen in figure 1.

I measured the timing, and it takes about 3 minutes from water input stopping to alarm ringing.

and that how one builds a water on and off detector with basic home items !

Friday, 7 February 2020

OOD - Online Book Reader

Untitled1

OOD for Online book reader

Requirements

  • User should be able to search in a library of books
  • Choose a book
  • Read a book
  • Turn pages of book

The code here will be pythonic version of the solution in CTCI here :

https://github.com/careercup/CtCI-6th-Edition/tree/master/Java/Ch%2007.%20Object-Oriented%20Design/Q7_05_Online_Book_Reader

Actors and use cases

  • User
    • Browses a library of books
    • Chooses a book
    • Book page is displayed to user
    • User turns page
    • User chooses new book to open

Classes and their responsibilities

  • Book
    • Represents a book and its content
  • User
    • Represents the user
  • Library
    • This will hold all the books
  • OnlineReaderSystem
    • This is composed of library, a user manager and a display unit
    • This also sets an active user and an active book
  • Display
    • Responsible for displaying the book
    • When user chooses a page that should be shown, like swipes to next page or back
  • UserManager
    • This takes care of addin and removing users from the system

online_reader_cd.png

In [45]:
class OnlineReaderSystem(object):
    def __init__(self):
        self._library = Library()
        self._user_manager = UserManager()
        self._display = Display()
        
        self._active_book = None
        self._active_user = None
        
    def get_library(self) -> Library:
        return self._library
    
    def get_user_manager(self) -> UserManager:
        return self._user_manager
    
    def get_display(self) -> Display:
        return self._display
    
    @property
    def active_book(self) -> Book:
        return self._active_book
    
    @active_book.setter
    def active_book(self, book: Book):
        self._active_book = book
        self._display.display_book(book)
        
    @property
    def active_user(self) -> User:
        return self._active_user
    
    @active_user.setter
    def active_user(self, user: User):
        self._active_user = user
        self._display.display_user(user)
        

class Library(object):
    def __init__(self):
        self.books = {}
        
    def add_book(self, book: Book):
        self.books[book.id] = book
        
    def remove_book(self, book: Book):
        self.remove_book(book.id)
        
    def remove_book(self, id_: int):
        del self.books[id_]
        
    def find_book(self, id_: int) -> Book:
        if id_ in self.books:
            return self.books[id_]
        else:
            return None
        

class UserManager(object):
    def __init__(self):
        self.users = {}
    
    def add_user(self, user: User):
        self.users[user.id] = user
    
    def remove_user(self, user: User):
        self.remove_user(user.id)
    
    def remove_user(self, id_: int):
        del self.users[id_]
        
    def find_user(self, id_) -> User:
        return self.users[id_]
    

class Display(object):
    def __init__(self):
        self._book = None
        self._user = None
        self._page_number = -1
        
    def display_user(self, user: User):
        self._user = user
        self._refresh_username()
    
    def display_book(self, book: Book):
        self._book = book
        
        self._refresh_title()
        self._refresh_details()
        self._refresh_page()
        
    def turn_page_forward(self):
        self._page_number = self._page_number + 1
        self._refresh_page()
        
    def turn_page_backward(self):
        self._page_number = self._page_number - 1
        self._refresh_page()
        
    # private methods
    def _refresh_username(self):
        print('The username update to : %s' % self._user.name)
        
    def _refresh_title(self):
        print('The title of book updated to : %s' % self._book.title)
        
    def _refresh_details(self):
        print('The details of book updated to : %s' % self._book.details)
        
    def _refresh_page(self):
        print('Refreshed the current page number : %d' % self._page_number)
        

class Book(object):
    def __init__(self, id_: int, title: str , details: str):
        self.id = id_
        self.title = title
        self.details = details
        

class User(object):
    def __init__(self, id_: int, name: str, account_type: int, details: str):
        self.id = id_
        self.name = name
        self.account_type = account_type
        self.details = details
        
    # other user relate methods
    def renew_membership(self):
        pass
    
    
In [46]:
class OnlineReaderSystemTestCLI(object):
    def __init__(self):
        self.reader = OnlineReaderSystem()
        
    def start(self):
        # add some books to library
        library = self.reader.get_library()
        
        rmy = Book(1001, 'Ramayana', 'Story of how Raama came back')
        mbt = Book(2002, 'Mahaabhaarata', 'Story of Pandavas and Kauravas')
        library.add_book(rmy)
        library.add_book(mbt)
        
        # add some users to user manager
        user_manager = self.reader.get_user_manager()
        
        ram = User(1, 'Rameshvara', 0 , 'Premium User')
        lak = User(2, 'Lakshmana', 1, 'Standard User')
        user_manager.add_user(ram)
        user_manager.add_user(lak)
        
        # now lets set a book and user in the system
        self.reader.active_user = ram
        self.reader.active_book = rmy
        
        # now lets flip the pages
        display = self.reader.get_display()
        display.turn_page_forward()
        display.turn_page_forward()
        display.turn_page_backward()
        
In [47]:
cli = OnlineReaderSystemTestCLI()
cli.start()
The username update to : Rameshvara
The title of book updated to : Ramayana
The details of book updated to : Story of how Raama came back
Refreshed the current page number : -1
Refreshed the current page number : 0
Refreshed the current page number : 1
Refreshed the current page number : 0