UNESCO Hackathon at FOSSASIA Summit 2019

As part of the celebration of the International Year of Indigenous Languages, the UNESCO and FOSSASIA once again joined hands in organizing a hackathon titled “Hack the Future”, aiming to preserve indigenous languages through free and open source software. The event took place from Mar 15 to Mar 17, during the FOSSASIA Summit 2019 at Lifelong Learning Institute, Singapore. The competition recorded a number of 193 registered participants from across Asia and neighboring regions. 15 projected ideas were submitted and 13 of them were pitched for 5 winning prizes.

The winning projects

For the expected outcome of the hack, the applications or games shall help to provide greater access to multilingual information and knowledge and enable knowledge-sharing and dissemination of good practices, specifically with regard to indigenous languages. All work shall be FOSS/Open Source and use or connect to FOSSASIA projects (APIs) and technologies to improve people’s lives and tackle indigenous languages and culture protection challenges.

The teams that met requirements and produced convincing solutions were:

  • Open Science Prize: Gadon
  • AI Dev Prize: Crowd-sourced Corpus Generation
  • Cloud Prize: Guageland
  • Indigenous Prize: Thazin
  • Audience Prize: Crowd-sourced Corpus Generation

Crowd Sourced Corpus Generation: the 5-member Indian hack team has built a crowd-sourced corpus generator that provides reliable crowd translations using AI matrix. The app contains of 2 major parts: (1) users’ translations input and (2) a platform where researchers and/or indigenous language experts can verify and give feedback on crowd translations.

Crowd-sourced Corpus Generation project team

Thazin is a mobile game project whose inspirations derived from flappy bird and Google Chrome’s “not connected” dinosaur game. In this game, a player needs to use particular indigenous languages to speak into the built-in microphone in order to get the bird to overcome obstacles of each level. The dataset is also generated from indigenous people themselves when they record their voices for players’ references.

Thazin project team

Gadong is another mobile game application designed to tackle the inadequacy of online resources for indigenous languages by providing a crowd-source dictionary for Khmu language. Gadon project not only aims to promote Khmu language to the public but also helps the Khmu people to learn English as a global language.

Gadong project team

GuageLand game application allows players to level up by learning and solving problems related to indigenous languages. The project is fully open source featuring technologies such as: SUSI.AI, react.js, node.js, Amazon-DynamoDB, html5, css3, javascript, NoSQL Database, PWA, and open data.

GuageLand project team

Participants, mentors and judges

The UNESCO Hackathon at FOSSASIA Summit 2019 received the participation of 193 candidates from 21 countries all over the world. Indians accounted for the largest number of participants (82), followed by Indians (62). And more than 20% of the participants were females.

Mentors

Seventeen open source advocates from Singapore, India, Vietnam, Sri Lanka, Germany, and indigenous experts from the Mekong region were invited to become mentors of the two-day hackathon. Mentors dedicatedly worked alongside with participants, giving them constructive feedback on the groups’ projects as well as showing them how to turn their ideas into feasible mobile app solutions. Some indigenous experts also joined the hacking projects as participants resulted in great diverse backgrounds of team members for each team.

Judges

The Hackathon jury consisted of UNESCO delegates, indegious languages experts and representatives from FOSSASIA, Microsoft, IBM, SUSI.AI and OpnTech. Some members from the jury board were mentors themselves. Thus, they not only provided support, made final evaluations on submitted projects but also encouraged participants to carry on their research after the  completion so that they can implement the applications into real life situations to empower the indeginous languages and culture through FOSS.

Conclusion

The event was another great achievement for both partners based on the quality of projects’ outcomes and the awareness of the concepts raised before, during and after the competition. With the support from UNESCO nominated indigenous experts, the young developers successfully developed innovative open source applications that support the dissemination of good practices with regard to indigenous languages and increase access to multilingual information and knowledge by leveraging open data and knowledge-sharing.

Links

Hackathon sessions at FOSSASIA Summit 2019: https://youtu.be/J53lT5IhkjY

FOSSASIA Summit 2019 Photos: https://photos.app.goo.gl/zrJnma6s1a1xPCu89

FOSSASIA on Twitter: https://twitter.com/fossasia

FOSSASIA Videos: https://www.youtube.com/fossasiaorg

FOSSASIA Calendar: https://calendar.fossasia.org



Continue Reading

Open is Becoming the New Common Foundation across Business, Government, Science, and Industry

Interview with Shanker V Selvadurai, Vice President & Chief Technology Officer of Cloud and Cognitive Software for IBM Asia Pacific

Could you briefly introduce yourself?

I am Shanker Selvadurai and currently the Vice President & Chief Technology Officer of Cloud and Cognitive Software for IBM Asia Pacific. I am based in Singapore and lead the technical organization that helps clients across Asia Pacific to explore and co-create cloud-based solutions that leverage data, analytics and artificial intelligence (AI) capabilities to deliver better decisions and outcomes.

I joined IBM in 2006.  Prior to IBM, I held key leadership positions in areas of research, development, consulting, sales and marketing with technology companies like AT&T, NCR and Fujitsu as well as start-up BlueGill Technologies. During this period I lead teams varying in size from 6 to over 1,000 while being based in North America, Europe and Asia.

I have a Bachelor of Science degree and a Master of Business Administration. I am also an Open Group Certified Distinguished Architect. Besides having published international patents/papers, I have actively contributed to international technology standards committees that include the IFX Forum, OFX Consortium and the Microsoft Advisory Council. I was also an adjunct lecturer at the Singapore Management University, teaching courses related to Services Science and Advanced Business Technology.

Tell us about your session at the FOSSASIA Summit, what will you cover?

At the FOSSASIA Summit, I am participating in a panel on “Business, Government, Science – What Opportunities Does “Open” Bring to Society”.  I hope to share IBM’s involvement in the open source movement, how businesses like IBM benefit from open source, as well as share thoughts about approaching open contribution and open governance in the future.

Shanker V Selvadurai handing over IBM Cloud Prize for Hackathon Winners

Business, Government, Science – What Opportunities Does “Open” Bring to Society from your point of view?

Open is becoming the new common foundation across business, government, science, and industry today.  For example, companies that still compete head-to-head in the marketplace are coming together to collaborate in open source communities.  They contribute to open source software and use it in their own IT systems and applications. They gain a competitive advantage — even though they may be helping their competitors in the short run.  The data demonstrates that companies with open source programs see more benefits from open source code and community participation.

IBM Connecting with Open Source Community at FOSSASIA Summit
International IBM Team Participating in FOSSASIA Summit

What is the role of Free Open Source Software in cloud and AI solutions in IBM?

Our offering portfolio, especially for our growth initiatives such as cloud and AI, is based on a solid foundation of open technologies.  Most of our strategic initiatives are founded on open source projects or communities, and we work across a wide variety of internal stakeholders to ensure that that the contributions we make to the community also provide greater value to our clients.

IBM Training on Open Source Cloud and AI Technologies at FOSSASIA OpenTechSummit
Many Open Source Developers Connect with IBM At the Booth

What was your motivation to work for IBM and to participate in the FOSSASIA Summit?

IBM has a long history as a leader in, and supporter of open source communities, most notably in the Apache, Linux, and Eclipse Foundations.  I joined IBM to help continue this tradition and I am looking forward to discussing new ideas to help build the future of open source at FOSSASIA Summit.

Which FOSS projects in the area of cloud and AI can interested developers contribute in IBM? In which domains could you use some help?

IBM believes that communities with open governance and an inclusive philosophy will attract the largest ecosystems and markets.  For a listing of some of the top open source projects that IBM believes represent significant opportunity areas, I would like to share with information how IBM supports high-impact open source projects here.

Participants from Around the World Following IBM Keynote on FOSS Collaboration

Which new features can we expect in IBM cloud and AI this year? Do you plan to release any new projects as FOSS?

Most of our strategic initiatives today are founded on open source projects or communities (Cloud Native Computing, Hyperledger, CD Foundation, etc.), and we work across a wide variety of internal stakeholders to ensure that that the contributions we make to the community also provide greater value to our clients. For a specific example of open source innovation from IBM, please check out the Egeria Project, which was founded in part by IBM.

Shanker V Selvadurai with Panelists and FOSSASIA Founder Ms. Hong Phuc Dang at the Singapore Summit 2019

As well, at the FOSSASIA Summit in Singapore, IBM shares the “Call for Code Global Challenge, which IBM is the Founding Partner.  

This multi-year global initiative rallies developers to create practical, effective, and high-quality applications based on cloud, data, and artificial intelligence that can have an immediate and lasting impact on humanitarian issues.  Call for Code brings startup, academic, and enterprise developers together and inspires them to solve the most pressing societal issues of our time. Building on the success of the 2018 competition, the 2019 Call for Code Global Challenge again asks developers to create solutions that significantly improve preparedness for natural disasters and accelerate relief when they hit. This year’s challenge introduces an emphasis on individual health and community wellbeing. This includes solutions that can reduce the risk of disease, improve access to data and the availability of resources, and address the mental health needs of those impacted before, during, and after disasters.

Hands-on Training with IBM Cloud and AI Experts at FOSSASIA Summit
Hands-on Training with IBM Cloud and AI Experts at FOSSASIA Summit
Continue Reading

10 Years FOSSASIA Anniversary OpenTechSummit 2019 Taking Place in Singapore

We are thrilled to update you with the amazing line-up at the 10 Years Anniversary Summit. The event is co-organized by the Lifelong Learning Institute and SkillsFuture under the theme “The Future is FOSS”.

Highlights of the FOSSASIA Anniversary Summit 2019 include:

  • Thu Mar 14 12:30 – Sun Mar 17 16:00 Exhibition: Showcases and job opportunities with tech companies and FOSS projects: Overview
  • Fri Mar 15 9:00 Cloud and AI Workshops: Join us for two intensive workshops with IBM experts from around the world on the latest technologies, development and deployment covering ‘Cloud, Containers and DevOps’ and developing ‘Machine Learning and Artificial Intelligence’ applications at the FOSSASIA Summit. Seats are limited. Sign up here.
  • Fri March 15 16:30 SUSI.AI – Create Skills for Your AI Solution: Sign up
  • Fri Mar 15 / Sat Mar 16 19:00 FOSSASIA Academy: Learn new tech skills in free introductory level technology workshops conducted with BuildingBloCS Computing students from Singapore. Topics include Introduction to Python, ML with Python, SQLite, MongoDB,  Vue.js, SUSI.AI Sign up to reserve.
  • Fri Mar 15 – Sun Mar 17 OpenTech Hackathon with UNESCO: Build open source apps and win prizes. Join Friday or Saturday.
  • Sat Mar 16 12:00 Capture the Community: Singapore Open Source Picture Taking and Birthday Cake. Join us
  • Sat Mar 16 13:30 Azure Kubernetes Service (AKS): Learn how to setup Kubernetes on Azure. Sign up here.
  • 12 Conference Tracks: Join talks by industry experts from IBM, Google, Oracle, Microsoft, Flowchain, Red Hat, Alibaba, Sysdig, Pivotal, Elastic, Codethink, Gitcoin and open source projects like VLC, Linux, CentOS, SELinux, Debian, Kubernetes, Lionsforge, Tensorflow, PostgreSQL, MySQL, FreeBSD, ReactJS, the Blockchain community as well as hardware experts from the Raspberry Pi Foundation, ARM, Bunnie Huang from Chibitronics, Mitch Altman and many more. We will be covering Conference Tracks such as AI, Blockchain and Cybersecurity: Schedule
  • Daily: Social Events: Pub crawls and city tours along with other techies from around the world! Sign up.

Meet companies, FOSS projects and communities and do hands-on workshops in the Exhibition:

  • Participate in workshops like doing experiments with Pocket Science Lab or Learn Soldering with Mitch Altman (Thu Mar 14 14:00, Fri Mar 15 14:00, Sat Mar 16, 14:00)
  • Get together with community developers and reps from Fosdem, CCC, Openfest, Linux Foundation, OSI and many companies and projects in the Hackers Lounge on Floor 1.
  • Exhibition Booths and Job Board: See showcases and find out about job opportunities from industry-leading companies and sponsors like IBM, UNESCO, Google, Indeed, Microsoft, Facebook, Flowchain, MySQL/Oracle, Singapore companies like Singapore Press Holdings and more: Overview 

Don’t miss out on our Social Events:

  • Sat Mar 16 19:00 10 Years FOSSASIA Party with Buffet, Live Music, Indian Dance, Chinese Performance & Cultural Program** : Celebrate FOSSASIA 10th Anniversary Party with us! Featuring Live Music, Cultural Highlights and Good Food! Indian dance, magic, music, Karaoke and so much more! (Social Event Tickets Required) : Tickets 
  • Wed Mar 13 15:00 FOSSASIA Meet & Greet: Join the FOSSASIA Speakers and Attendees Meet & Greet, meet the local tech scene, explore Singapore in a Culture and Exploration Wednesday Afternoon, and enjoy the taste of Asia at a local dinner: Attendance
  • Thu Mar 14 19:00 Welcome Dinner: With FOSSASIA Summit Speakers and Exhibitors: Attendence
  • Fri Mar 15 7:00 Cultural Morning Tour to Merlion Statue and View of Marina Bay: Attendence
  • Fri Mar 15 19:00 Chinatown & Clarke Quay Snacks and Pub Crawl: Network with speakers and participants of the FOSSASIA OpenTech Summit for a Chinatown and Clarke Quay Snacks an Pub Crawl on Friday Evening: Attendance
  • Sun Mar 17 20:30 Dim Sum and Midnight Hacks: Didn’t get enough of techie stuff? Want to work on this awesome project you found at FOSSASIA? Met some amazing developers at the weekend? Join us for the FOSSASIA After-Event hacking, coding, relaxing at Hackerspace.sg on Sunday evening: Attendance
  • Mon Mar 18 12:00 Community Lunch: Gather with us on Monday Noon for yummy local Singapore food: Attendance

FOSSASIA Summit – Schedule Roster


Featured Speakers and Sessions

We have more than 180 speakers and close to 200 sessions where participants can learn how to work with Cloud solutions, train their personal AI, create voice interfaces, build their own Operating Systems, create AR and VR apps for the web, learn about databases or prepare for Linux certification. Find out more about the speakers.


FOSSASIA Summit Theme: The Future is FOSS

Today we see that Free and Open Source is mainstream. The large online providers are offereing their services mainly based on FOSS solutions. FOSSASIA is part of a movement advancing FOSS to the next level developing not just software, but also Open Hardware like the Pocket Science Lab. The FOSS model provides us with a way to collaborate easily, freely and efficiently and it can help us to solve the problems of this planet together. Let’s do it at the FOSSASIA OpenTechSummit! The theme of the event is “The Future is FOSS”.


Thank you for sponsoring!

Thank you to our sponsors IBM, Google Open Source, Microsoft, Indeed.com, Flowchain, Facebook, MySQL/Oracle, SPH and partners for supporting the event!


Thank you for celebrating FOSSASIA’s 10th Anniversary with us.

Do follow us on our Social Media accounts to get the latest updates on the Summit and other Open Tech stuff.

We can’t wait to see you to share and gain techie knowledge with and from you!

Continue Reading

Reducing the YouTube response time by 90%

In this blog post, we are going to cover how the audio from Youtube is being used in SUSI Smart Speaker and how we reduced the response time from ~40 seconds to ~4 seconds for an average music video length.

First Approach

Earlier, we were using MPV player’s inbuilt feature to fetch the YouTube music. However, MPV player was a bulky option and the music server had to be started every time before initiating a music video.

video_process = subprocess.Popen([‘mpv’, ‘–no-video’, ‘https://www.youtube.com/watch?v=’ + video_url[4:], ‘–really-quiet’]) # nosec #pylint-disable type: ignore requests.get(‘http://localhost:7070/song/’ + video_url) self.video_process = video_process stopAction.run() stopAction.detector.terminate()

Making it Efficient

To reduce the response time, we created a custom Music Server based on Flask,python-vlc and python-pafy which accepts requests from the main client and instructs the System to play the music with just 90% more efficiency.

app = Flask(__name__)

Instance = vlc.Instance(‘–no-video’)

player = Instance.media_player_new()

url = @app.route(‘/song’, methods=[‘GET’])

def youtube():

    vid = request.args.get(‘vid’)

    url = ‘https://www.youtube.com/watch?v=’ + vid

    video = pafy.new(url)
    streams = video.audiostreams 

    best = streams[3]

    playurl = best.url

    Media = Instance.media_new(playurl)

    Media.get_mrl()

    player.set_media(Media)

    player.play()

    display_message = {“song”:“started”}

    resp = jsonify(display_message)

    resp.status_code = 200

    return resp

However, shifting to this Server removed the ability to process multiple queries and hence we were unable to pause/play/stop the music until it completed the time duration. We wanted to retain the ability to have ‘play/pause/stop’ actions without implementing multiprocessing or multithreading as it would’ve required extensive testing to successfully implement them without creating deadlocks and would’ve been overkill for a simple feature.

Bringing Back the Lost Functionalities

The first Step we took was to remove the vlc-python module and implement a way to obtain an URL that we use in another asynchronous music player.

@app.route(‘/song’, methods=[‘GET’])
def youtube():

    vid = request.args.get(‘vid’)

    streams = video.audiostreams

    best = streams[3]

    playurl = best.url 

    display_message = {“song”: “started”, “url”: playurl}

    resp = jsonify(display_message)

    resp.status_code = 200

    return resp

The next issue was to actually find a way to run the Music Player asynchronously. We used the `subprocess. Popen` method and cvlc to play the songs asynchronously.

try:

    x = requests.get(‘http://localhost:7070/song?vid=’ + video_url[4:])

    data = x.json()

    url = data[‘url’]

    video_process = subprocess.Popen([‘cvlc’, ‘http’ + url[5:], ‘–no-video’])

    self.video_process = video_process

except Exception as e:

    logger.error(e);

And this is how we were able to increase the efficiency of the music player while maintaining the functionalities.

References

Continue Reading

Integrating Redux with SUSI.AI Web Clients

In this blog post, we are going to go through the implementation of the Redux integration on the SUSI.AI web clients. The existing SUSI.AI WebChat codebase has Flux integrated into it, but integrating Redux would make it a lot easier to manage the app state in a single store. And would result in a more maintainable and performant application. Let us go through the implementation in the blog –

The key steps involved the following –

  • Restructuring the directory structure of the repository to enable better maintenance.
  • Creating a Redux store and configuring the middlewares.
  • Standardizing the format for writing actions and make API calls on dispatching an action.
  • Standardizing the format for writing reducers.
  • Hook the components to the Redux store.

Restructuring the directory structure

DIrectory structure for https://chat.susi.ai
  • All the redux related files and utils are put into the redux directory, to avoid any sort of confusion, better maintenance and enhanced discoverability. The prime reason for it also because the integration was done side-by-side the existing Flux implementation.
  • The actions and reducers directory each has a index.js, which exports all the actions and reducers respectively, so as to maintain a single import path for the components and this also helped to easily split out different types of actions/reducers.

Creating Redux store and configure middlewares

import { createStore as _createStore, applyMiddleware } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import reduxPromise from 'redux-promise';
import reducers from './reducers';

export default function createStore(history) {
 // Sync dispatched route actions to the history
 const reduxRouterMiddleware = routerMiddleware(history);
 const middleware = [reduxRouterMiddleware, reduxPromise];

 let finalCreateStore;
 finalCreateStore = applyMiddleware(...middleware)(_createStore);

 const store = finalCreateStore(
   reducers,
   {},
   window.__REDUX_DEVTOOLS_EXTENSION__ &&
     window.__REDUX_DEVTOOLS_EXTENSION__(),
 );

 return store;
}
  • The function createStore takes in the browserHistory (provided by React Router) and returns a single store object that is passed on to the entry point component of the App.
  • The store is passed to the application via the <Provider> component, provided by the react-redux. It is wrapped to the <App> component as follows –

ReactDOM.render(
 <Provider store={store} key="provider">
   <App />
 </Provider>,
 document.getElementById('root'),
);
  • The 2 middlewares used are routerMiddleware provided by the react-router-redux and the reduxPromise provided by redux-promise.
  • The routerMiddleware enhances a history instance to allow it to synchronize any changes it receives into application state.
  • The reduxPromise returns a promise to the caller so that it can wait for the operation to finish before continuing. This is useful to assist the application to tackle async behaviour.

Standardizing the actions and making API calls on action dispatch

  • The actions file contains the following –

import { createAction } from 'redux-actions';
import actionTypes from '../actionTypes';
import * as apis from '../../apis';

const returnArgumentsFn = function(payload) {
 return Promise.resolve(payload);
};

export default {
// API call on action dispatch
 getApiKeys: createAction(actionTypes.APP_GET_API_KEYS, apis.fetchApiKeys),
// Returns a promise for actions not requiring API calls
 logout: createAction(actionTypes.APP_LOGOUT, returnArgumentsFn),
};

  • As new actions are added, it can be added to the actionTypes file and can be added in the export statement of the above snippet. This enables very standard and easy to manage actions.
  • This approach allows to handle both types of action dispatch – with and without API call. In case of API call on dispatch, the action resolves with the payload of the API.
  • The APIs are called via the AJAX helper (Check out this blog – https://blog.fossasia.org/make-a-helper-for-ajax-requests-using-axios/ ).

Standardizing the reducers and combining them

  • The reducers file contains the following –

import { handleActions } from 'redux-actions';
import actionTypes from '../actionTypes';

const defaultState = {
 ...
 apiKeys: {},
 ...
};

export default handleActions({
  [actionTypes.APP_GET_API_KEYS](state, { payload }) {
     const { keys } = payload;
     return {
       ...state,
       apiKeys: { ...keys },
     };
  },
  ...
},defaultState);
  • The default application state is defined and the reducer corresponding to each action type returns an immutable object which is the new application state,
  • In the above example, the payload from the getApiKeys API call is received in the reducer, which then updated the store.
  • The reducers/index.js  combines all the reducers using combineReducers provided by redux and exports a single object of reducers.

import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import app from './app';
import settings from './settings';
import messages from './messages';

export default combineReducers({
 routing: routerReducer,
 app,
 settings,
 messages,
});

Hook the components to the Redux store

  • After Redux integration and standardization of the reducers, actions, any of the component can be hooked to the store as follows –

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

class MyComponent extends Component {
 componentDidMount() {
    // Dispatch an action
    this.props.actions.getApiKeys();
 }
 render() {
   const { apiKeys } = this.props;
   return (
     <div>
        /* JSX */
     </div>     
   );
 }
}

function mapStateToProps(store) {
 const { apiKeys } = store.app;
 return {
   apiKeys
 };
}

function mapDispatchToProps(dispatch) {
 return {
   actions: bindActionCreators(actions, dispatch),
 };
}

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
  • The mapStateToProps is a function that is used to provide the store data to the component via props, whereas mapDispatchToProps is used to provide the action creators as props to the component.

The above was the implementation of Redux in the SUSI.AI Web Clients. I hope the blog provided a detailed insight of how Redux was integrated and the standards that were followed.

References

Continue Reading

Make a helper for AJAX requests using axios

In this blog post, we are going to go through the implementation of the helper function that is created for making AJAX requests using axios. Currently, the AJAX calls are made in a very random manner where the calls are written in the component itself and involves rewriting of headers, etc for the API call. Let us go through the implementation in the blog, which will standardise the way to make API calls in SUSI.AI web clients.

The primary changes are –

  • Making a common helper for AJAX requests with the help of axios.
  • Making a common file containing all the API calls across the project.

Going through the implementation

The API calls within the repository were not being made in an organised way, also a lot of redundant code was present. The aim of creating the helper is that, all the API calls is called via this common function. It takes care of the headers and also sending access_token with the API if the user is already logged in for API calls requiring authentication. The function for a API request now looks this simple –

// API call for signup
export function getSignup(payload) {
 const { email, password } = payload;
 const url = `${API_URL}/${AUTH_API_PREFIX}/signup.json`;
 return ajax.get(url, { signup: email, password });
}
  • In the above snippet, the ajax is the common helper used for making API calls. ajax is an object of functions that returns a promise for  various methods of API requests
  • We have primarily taken into consideration GET & POST requests type.
  • The helper function is as follows –
/* Insert imports here*/
const cookies = new Cookies();
const obj = {};

['get', 'post', 'all'].forEach(function(method) {
 obj[method] = function(url, payload, settings = {}) {
   /* Request will be aborted after 30 seconds */
   settings = {
     timeout: 30000,
     dataType: 'json',
     crossDomain: true,
     ...settings,
   };
   
   // Check if logged in
   if (cookies.get('loggedIn')) {
     payload = {
       access_token: cookies.get('loggedIn'),
       ...payload,
     };
   }

   return new Promise(function(resolve, reject) {
     let methodArgs = [];
     if (method === 'post') {
       if (payload && payload instanceof FormData !== true) {
           // Convert to Form Data
           payload = toFormData(payload);
       }

       settings.headers = {
         'Content-Type': 'application/x-www-form-urlencoded',
         ...settings.headers,
       };
     } else if (method === 'get') {
       if (payload) {
         // Add params to the URL   
         url += `?${Object.keys(payload)
           .map(key => key + '=' + payload[key])
           .join('&')}`;
       }
     }

     const methodsToAxiosMethodsMap = {
       get: 'get',
       post: 'post',
       all: 'all',
     };

     if (method === 'all') {
       methodArgs = [url];
     } else if (method === 'get') {
       methodArgs = [url, settings];
     } else {
       methodArgs = [url, payload, settings];
     }

     axios[methodsToAxiosMethodsMap[method]].apply({}, methodArgs).then(
       function(data = {}, ...restSuccessArgs) {
         const statusCode = _.get(data, 'status');
         /*  Send only api response */
         let responseData = { statusCode, ..._.get(data, 'data') };

         if (method === 'all') {
           responseData = data;
           responseData.statusCode = statusCode;
         }

         if (payload) {
           responseData.requestPayload = payload;
         }
         // Mark the promise resolved and return the payload
         resolve(camelizeKeys(responseData), ...restSuccessArgs);
       },
       function(data = {}, ...restErrorArgs) {
         // If request is canceled by user
         if (axios.isCancel(data)) {
           reject(data);
         }

         const statusCode = _.get(data, 'response.status', -1);
         let responseData = { statusCode, ..._.get(data, 'response.data') };

         if (method === 'all') {
           responseData = data;
           responseData.statusCode = statusCode;
         }

         if (payload) {
           responseData.requestPayload = payload;
         }
         // Mark the promise rejected and return the payload
         reject(camelizeKeys(responseData), ...restErrorArgs);
       },
     );
   });
 };
});

export default obj;
  • The above objects contains 3 functions –
    • ajax.get(url, payload, settings) – GET – The helper adds the query params to the URL by iterating through them and appending it to the URL and joining them with &.
    • ajax.post(url, payload, settings) –  POST – The helper checks, if the POST requests contains a payload which is an instance of form data, it converts to toFormData payload.
    • ajax.all(url, payload, settings) – ALL – It helps to deal with concurrent requests.
  • The url is the complete API endpoint, payload consists of the data/request payload. The settings consists of any headers related info, that needs to be added exclusively to the axios config.
  • There is also no need to pass access token to each API request as a payload. The helper check whether the user is logged-in and adds the access_token to the request payload. The snippet below demonstrates it –
if (cookies.get('loggedIn')) {
     payload = {
       access_token: cookies.get('loggedIn'),
       ...payload,
     };
   }
  • The access token, if present in the cookies is added to the payload, therefore authenticating the API call.
  • The keys of the response are changed to camel case before being sent to the caller function. It is done to maintain variable nomenclature standards across the app and also to follow javascript guidelines.
  • The file containing the API calls is structured as follows –
import ajax from '../helpers/ajax';
import urls from '../utils/urls';

const { API_URL } = urls;
const AUTH_API_PREFIX = 'aaa';
const CHAT_API_PREFIX = 'susi';
const CMS_API_PREFIX = 'cms';

// API without request payload
export function fetchApiKeys() {
 const url = `${API_URL}/${AUTH_API_PREFIX}/getApiKeys.json`;
 return ajax.get(url);
}

// API with request payload
export function getLogin(payload) {
 const { email, password } = payload;
 const url = `${API_URL}/${AUTH_API_PREFIX}/login.json`;
 return ajax.get(url, { login: email, password, type: 'access-token' });
}

The above was the implementation of the helper function that is created for making AJAX requests using axios. I hope the blog provided a detailed insight of it helps in making the process of making API calls more standardised and easier.

References

Continue Reading

Adding 3D Home Screen Quick Actions to SUSI iOS App

Home screen quick actions are a convenient way to perform useful, app-specific actions right from the Home screen, using 3D Touch. Apply a little pressure to an app icon with your finger—more than you use for tap and hold—to see a list of available quick actions. Tap one to activate it. Quick actions can be static or dynamic.

We have added some 3D home screen quick action to our SUSI iOS app. In this post, we will see how they are implemented and how they work.

The following 3D home screen quick actions are added to SUSI iOS:

  • Open SUSI Skills – user can directly go to SUSI skills without opening a chat screen.
  • Customize Settings – user can customize their setting directly by using this quick action.
  • Setup A Device – when the user quickly wants to configure his/her device for SUSI Smart Speaker, this is quick action is very helpful in that.
  • Change SUSI’s Voice – user can change SUSI message reading language accents directly from this quick action.

Each Home screen quick action includes a title, an icon on the left or right (depending on your app’s position on the home screen), and an optional subtitle. The title and subtitle are always left-aligned in left-to-right languages.

Step 1 – Adding the Shortcut Items

We add static home screen quick actions using the UIApplicationShortcutItems array in the app Info.plist file. Each entry in the array is a dictionary containing items matching properties of the UIApplicationShortcutItem class. As seen in screenshot below, we have 4 shortcut items and each item have three properties UIApplicationShortcutItemIconType/UIApplicationShortcutItemIconFile, UIApplicationShortcutItemTitle, and UIApplicationShortcutItemType.

  • UIApplicationShortcutItemIconType and UIApplicationShortcutItemIconFile is the string for setting icon for quick action. For the system icons, we use UIApplicationShortcutItemIconType property and for the custom icons, we use UIApplicationShortcutItemIconFile.
  • UIApplicationShortcutItemTitle is a required string that is displayed to the user.
  • UIApplicationShortcutItemType is a required app specific string used to identify the quick action.

Step 2 – Handling the Shortcut

AppDelegate is the place where we handle all the home screen quick actions. We define these variables:

var shortcutHandled: Bool!
var shortcutIdentifier: String?

When a user chooses one of the quick actions the launch of the system or resumes the app and calls the performActionForShortcutItem method in app delegate:

func application(_ application: UIApplication,
                     performActionFor shortcutItem: UIApplicationShortcutItem,
                     completionHandler: @escaping (Bool) -> Void) {
        shortcutIdentifier = shortcutItem.type
        shortcutHandled = true
        completionHandler(shortcutHandled)
    }

Whenever the application becomes active, applicationDidBecomeActive function is called:

func applicationDidBecomeActive(_ application: UIApplication) {
        // Handel Home Screen Quick Actions
        handelHomeActions()
    }

Inside the applicationDidBecomeActive function we call the handleHomeAction() method which handles the home screen quick action.

func handelHomeActions() {
       if shortcutHandled == true {
           shortcutHandled = false
           if shortcutIdentifier == ControllerConstants.HomeActions.openSkillAction {
               // Handle action accordingly
               }
           } else if shortcutIdentifier == ControllerConstants.HomeActions.customizeSettingsAction {
               // Handle action accordingly
           } else if shortcutIdentifier == ControllerConstants.HomeActions.setupDeviceAction {
               // Handle action accordingly
               }
           } else if shortcutIdentifier == ControllerConstants.HomeActions.changeVoiceAction {
               // Handle action accordingly
               }
           }
       }
   }

Final Output:

Resources –

  1. Home Screen Quick Actions – Human Interface Guidelines by Apple
  2. Adding 3D Touch Quick Actions by Use Your Leaf
  3. Apple’s documentation on performActionFor:completionHandler
Continue Reading

Adding report skills feature in SUSI iOS

SUSI.AI is having a various type of Skills that improving the user experience. Skills are powering the SUSI.AI personal chat assistant. SUSI skills have a nice feedback system. We have three different feedback way for SUSI skills, 5-star rating system, posting feedback, and reporting skills.

5-Star Rating – rate skills from 1 (lowest) to 5 (highest) star

Posting Feedback – user can post feedback about particular skill

Report Skill – user can report skill if he/she found it inappropriate

In this post, we will see how reporting skills feature work in SUSI iOS and how it is implemented. You can learn about 5-star rating here and posting feedback feature here.

Adding report skill button –

let reportSkillButton: UIButton = {
        let button = UIButton(type: .system)
        button.contentHorizontalAlignment = .left
        button.setTitle("Report Skill", for: .normal)
        button.setTitleColor(UIColor.iOSGray(), for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

In above, we have set translatesAutoresizingMaskIntoConstraints property for false. By default, the property is set to true for any view you programmatically create. If you add views in Interface Builder, the system automatically sets this property to false. If this property’s value is true, the system creates a set of constraints that duplicate the behavior specified by the view’s autoresizing mask.

Setting up report skill button –

We are setting constraints programmatically as we created button programmatically and set translatesAutoresizingMaskIntoConstraints to false. Also, setting a target to the button.

if let delegate = UIApplication.shared.delegate as? AppDelegate, let _ = delegate.currentUser {
            view.addSubview(reportSkillButton)
            reportSkillButton.widthAnchor.constraint(equalToConstant: 140).isActive = true
            reportSkillButton.heightAnchor.constraint(equalToConstant: 32).isActive = true
            reportSkillButton.leftAnchor.constraint(equalTo: contentType.leftAnchor).isActive = true
            reportSkillButton.topAnchor.constraint(equalTo: contentType.bottomAnchor, constant: 8).isActive = true

            reportSkillButton.addTarget(self, action: #selector(reportSkillAction), for: .touchUpInside)
        }

In the above method, we can see that we are only showing button if user is logged-in. Only a logged-in user can report the skill. To check if user is logged in or not, we are using the AppDelegate shared instance where we save the logged-in user globally when the user signs in.

When user clicks the Report Skill button, a popup is open up with a text field for feedback message like below:

This is how UI look like!

When user clicks the Report action after typing feedback message, we are using the following endpoint:

https://api.susi.ai/cms/reportSkill.json

With the following parameters –

  • Model
  • Group
  • Skill
  • Language
  • Access Token
  • Feedback

Here is how we are handling the API call within our app –

func reportSkill(feedbackMessage: String) {
        if let delegate = UIApplication.shared.delegate as? AppDelegate, let user = delegate.currentUser {

            let params = [
                Client.SkillListing.model: skill?.model as AnyObject,
                Client.SkillListing.group: skill?.group as AnyObject,
                Client.SkillListing.skill: skill?.skillKeyName as AnyObject,
                Client.SkillListing.language: Locale.current.languageCode as AnyObject,
                Client.SkillListing.accessToken: user.accessToken as AnyObject,
                Client.SkillListing.feedback: feedbackMessage as AnyObject
            ]

            Client.sharedInstance.reportSkill(params) { (success, error) in
                DispatchQueue.main.async {
                    if success {
                        self.view.makeToast("Skill reported successfully")
                    } else if let error = error {
                        self.view.makeToast(error)
                    }
                }
            }
        }
    }

On successfully reported skill, we show a toast with ‘Skill reported successfully’ message and if there is error reporting the skills, we present the toast with error as a message.

Resources –

  1. SUSI Skills: https://skills.susi.ai/
  2. Apple’s documentations on translatesAutoresizingMaskIntoConstraints
  3. Allowing user to submit ratings for skills in SUSI iOS
  4. Displaying Skills Feedback on SUSI iOS
Continue Reading

UNESCO Hackathon Vietnam 2018 Wrap Up

204 participants gathered at the UNESCO Hackathon over the weekend of October 13 – 14 in Ho Chi Minh City to develop digital applications that tackle climate change and sustainable development challenges in Vietnam and the Mekong region. The event was a great success thanks to support from the Government of Malaysia, UNESCO YouthMobile Initiative and Officience.

24 project teams were formed during the Hackathon. With the dedication of team members and mentorship from facilitators, all teams managed to complete their hacks. It was challenging for the judges to make their final decision as all proposed solutions appeared to be innovative and applicable. The three winning teams were Klima Kage, Climap & Bird’s Eye View. Additionally, the judges also selected three runner-ups ThreeWolves, DBTFC & GreenELF, whose projects directly address the issues related to climate change in the country.

Winning Projects: Klima Kage, Bird’s Eye View and Climap

Klima Kage is a website application which consists of two parts: main page and community page. The main page contains data from open source database and tutorials extracted from the UNESCO handbook for journalists on climate change and sustainable development in Asia Pacific, which directly assist journalists in selecting data to monitor.

On the community side, there is a forum for discussion and a news section where relevant articles will be published. The team decided to give priority to female journalists (ration 6:4) in reviewing and releasing news articles on this page, as a way to raise public awareness on gender dimension. SUSI.AI was also integrated into the web app to record users’ behaviour and offer suggestions for their next visits.

Klima Kage (Sieben) Team

Bird’s Eye View is a mobile game built in unity with an objective to educate people about the impacts of climate change on all kind of creatures under the sea. In each level of the game, players are brought into a different coastal city in Vietnam, where they learn about the real problems which are happening to the regional aquatic animals.

The game was designed to target on younger age groups, who generally have less awareness on environmental issues, yet are expected to create big differences in the community once they grow up. In the future, the development team hopes to expand the application, to include more terrains and other kinds of animals in order to provide players with a more overall image of the situation in Vietnam and the region.

Bird’s Eye View app presented by ‘Why triple teas?’ Team

Climap is the last project selected as a winner of the hackathon. Proposed and developed by a team of young developers from Ho Chi Minh City, Climap acts as an EXIF based Image Sharing System that enables users to to collect and instantly share data/images of places before, during and after disasters happen (due to the impacts of climate change). 

By using Climap, users can view all relevant data from the uploaded photos including: its location, weather index, and the occurred events/incidents, etc. They can write tags for each picture to label what was happening at that moment so the data can be further analyzed by local authorities or responsible institutions.

Climap by BIT Team

Talks and Workshops

Alongside with the hacking competition, tech talks and workshops were hosted to support the participants and provide them crucial knowledge of the topics.

Panel Discussion: A Green Planet for All

At the beginning of the hackathon, Hong Phuc Dang (FOSSASIA Founder) led a panel discussing featuring Misako Ito (UNESCO Advisor for Information and Communication), Pham Lan Phuong (Author Khai Don) and Tran Le Thu Giang (Youtuber GiangOi) to uncover the concepts of climate change and sustainable development under the own perspectives. The conversation offered the audience specific answers on how they can practice sustainable development in every aspects of their daily lives.

Panel Discussion: A Green Planet for All

Workshops: Working with Git/Github and Doing Electronics Experiments with PSLab

PadMal M, FOSSASIA/PSLab Lead Developer delivered two workshops, when he showed participants how contributors can effectively work together on an open source project using Github and what electronics experiments can be performed using PSLab (Pocket Science Lab – a hardware device by FOSSASIA). Together with FOSSASIA robotics expert, Marco Gutiérrez, the two successfully developed and integrated a robot into the PSLab device, which amazed participants and audience alike.

Learn how to perform scientific experiments using PSLab

Robotics integration on PSLab device by Marco Gutiérrez and Padmal M

Experience the world’ first portable CO2 Laser Cutter by LionsForge

Kee Wee Teng, Founder at LionsForge is a maker at heart, he always felt that the laser cutter, being such a useful tool, should be more accessible. He believed this type of machine should be safer so that everyone can use it for their own needs. After two years working on several designs and samples, Kee Wee and his team finally introduced to the world the CraftLaser laser cutter, a portable yet powerful machine that can be safely use at home, in the schools or even in public places.

Kee Wee Teng, Founder/CEO at LionsForge explained the CraftLaser’s operation procedures,

then shared how he successfully got the project fully funded from Indiegogo in just a week.

Video Footage of UNESCO Hackathon Vietnam 2018

Links

Hackathon Photos: https://photos.app.goo.gl/tJRN2b3mayNy6FcE6

FOSSASIA on Twitter: https://twitter.com/fossasia

FOSSASIA Videos: https://www.youtube.com/fossasiaorg

FOSSASIA Calendar: https://calendar.fossasia.org

Posts on the Web

UNESCO Bangkok: UNESCO Hackathon sets its sights on climate change solutions in Asia-Pacific

LionsForge Singapore: UNESCO Hackathon in Ho Chi Minh, Vietnam

Vietnamese-German University News: VGU students won first prize at UNESCO Hackathon Vietnam  

Share your write-ups about UNESCO Hackathon by making a tweet using hashtag #UNESCOHackathon #YouthMobile @fossasia @YouthMobile_ 

Continue Reading

Jugaad Fest Hyderabad on 30th September 2018 – Hack, Fix, Trick It, or Simply Make Open Tech Work for You

Jugaadfest is a gathering of developers and FOSS contributors who get together to learn, share, and hack on Open Source projects for one day with the goal of making things work. 30+ mentors and successful FOSSASIA Google Summer of Code students from India and Europe will guide you during the day. At Jugaadfest you can:

  • join various hands-on activities, e.g. set up FOSSASIA apps, install conversational voice assistants, do experiments with PSLab
  • learn from developers how to find innovative fixes or simple work-arounds to get FOSSASIA prototypes working
  • learn how to build up an awesome developer profile that improves your job chances by collaborating in the FOSS community
  • improve your coding and tech skills while contributing to open source software and hardware projects
  • enjoy presentations conducted by veteran developers

Jugaadfest is a hands-on event. Please bring your laptop.

We kick-off in the morning with short introductions by developers of FOSS projects. After that participants have the chance to join teams at different tables and start learning and collaborating on Open Tech projects.

At the lunch break participants mingle and discuss what they have learned before they continue browsing  projects. At the end of the event day we ask developers to share their learnings in short lightning talks.

Certificates: Participants of Jugaadfest receive a certificate of participation. (Prerequisite: Full-day participation)

Contributors Discount Tickets

You are a contributor to FOSSASIA project or other Open Source communities? Apply for a discount ticket. There is a limited number of contributor tickets for 90, 80, and 70% discounts available. Please fill in the form here: https://jugaadfest.com/community-ticket

AGENDA

Jugaadfest Hyderabad

  • Location: BVRIT HYDERABAD College of Engineering for Women
  • Date: Sunday, September 30, 2018
  • 8:30 Registration and Breakfast Snacks
  • 9:30 Introduction and Opening Sessions
  • 9:45 How to Participate in FOSSASIA Coding Programs, Google Summer of Code and Codeheat
  • 10:00 Project Presentations: SUSI.AI, Open Event Solutions, Pocket Science Lab, Meilix, Badgeyay
  • 11:00 Developers Join Project Tables
  • 12:30 Lunch Break
  • 13:30 Developers Learn and Participate at Project Tables
  • 16:00 How to Collaborate in International Open Source Projects and Global Enterprises Using Best Practices
  • 16:15 Lightning Talks
  • 16:30 What’s Next?
  • 17:00 End of Event

Social Event (Ticket Required)

  • Date: Sunday, September 30, 2018
  • 19:30 Dinner in Hyderabad City

Jugaadfest Extended (Contributors – Invitation Only)

  • Location: Co-Working Hyderabad
  • Developer Workshops: Monday October 1 – Wednesday, October 3, 2018
  • Brunch: Thursday, October 4, 2018

LINKS

Continue Reading
Close Menu