Skip to content

Commit

Permalink
Merge pull request #145 from renderforest/new-methods
Browse files Browse the repository at this point in the history
✨ release 0.3.6 : new screen, area methods
  • Loading branch information
narekhovhannisyan authored Jan 23, 2019
2 parents 3310e67 + a7fad2d commit 8f4392c
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 37 deletions.
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Welcome to the Renderforest API! You can use our API to:
- [Set voice-over](#set-voice-over)
- [Set mute music](#set-mute-music)
- [Set sounds](#set-sounds)
- [Set screen duration](#set-screen-duration)
- [Set icon position](#set-the-icon-position)
- [Set text on text holder area](#set-text-on-text-holder-area)
- [Set image on image holder area](#set-image-on-image-holder-area)
- [Set video on video holder area](#set-video-on-video-holder-area)
Expand Down Expand Up @@ -482,6 +484,46 @@ const sounds = [ sound1, sound2 ]
projectDataInstance.setSounds(sounds)
```

##### Set screen duration

It's possible to check if `screen` duration is adjustable, get current screen duration via `calculateScreenDuration`,
get maximum possible duration for current screen, and to set your desired duration.
```js
const screens = projectDataInstance.getScreens()

if (screens && screens[0]) {
const isAdjustable = screens[0].isDurationAdjustable()

if (isAdjustable) {
const calculateDuration = screens[0].calculateScreenDuration()
console.log(calculateDuration)
const maxDuration = screens[0].getMaxPossibleDuration()
const desiredDuration = 5

if (desiredDuration <= maxDuration) {
screens[0].setDuration(desiredDuration)
}
}
}
```

##### Set icon position

There is two methods `isIconPositionAdjustable` and `toggleIconPosition`.
The first one checks if it's possible to adjust icon position. If it returns `0` then it's not possible,
if a number is greater than `0` it means that icon position is adjustable.
The value `1` stands for the right position, accordingly, the value `2` stands for left position.
For changing the icon position here is `toggleIconPosition` method. It changes icon position value `1<-->2`.
```js
const screens = projectDataInstance.getScreens()

if (screens && screens[0]) {
if (screens[0].isIconPositionAdjustable()) {
screens[0].toggleIconPosition()
}
}
```

##### Set text on text holder area
```js
const screens = projectDataInstance.getScreens()
Expand Down
30 changes: 27 additions & 3 deletions examples/project-data/update-project-data-partial-advanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,41 @@ async function sample () {
voiceOver: false
}

const sounds = [ sound1, sound2 ]
const sounds = [sound1, sound2]
projectDataInstance.setSounds(sounds)

const screens = projectDataInstance.getScreens()
// set text on text holder area
if (screens && screens[0]) {
// check if screen duration is adjustable do some manipulations
const isAdjustable = screens[0].isDurationAdjustable()

if (isAdjustable) {
const calculateDuration = screens[0].calculateScreenDuration()
console.log(calculateDuration)
const maxDuration = screens[0].getMaxPossibleDuration()
const desiredDuration = 5

if (desiredDuration <= maxDuration) {
screens[0].setDuration(desiredDuration)
}
}
// check if icon position is adjustable, then change the icon position
if (screens[0].isIconPositionAdjustable()) {
screens[0].toggleIconPosition()
}

const areas = screens[0].getAreas()

const area = areas[0]
if (area && area.type === 'text') {
area.setText('sample text')
// check recommended character count for current area
const recommendedCharacterCount = area.getRecommendedCharacterCount()
const sampleText = 'sample text'

if (sampleText.length <= recommendedCharacterCount) {
area.setText(sampleText)
}
}
}
// set image on image holder area
Expand Down Expand Up @@ -145,7 +169,7 @@ async function sample () {
areas: [
{
id: 3562168,
cords: [ 656, 224, 1048, 224, 1048, 332, 656, 332 ],
cords: [656, 224, 1048, 224, 1048, 332, 656, 332],
height: 108,
order: 0,
title: 'char_Angry_2',
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@renderforest/sdk-node",
"description": "Renderforest SDK for Node.js",
"version": "0.3.5",
"version": "0.3.6",
"author": "RenderForest LLC",
"bugs": {
"url": "https://github.com/renderforest/renderforest-sdk-node/issues"
Expand Down
98 changes: 92 additions & 6 deletions src/classes/project-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@

const PackageJson = require('../../package.json')

const { MissingOrderError } = require('../util/error')
const {
CharacterBasedDurationError,
DurationGreaterThanMaxPossibleError,
IconAdjustableError,
MissingOrderError,
ScreenHasVideoAreaError
} = require('../util/error')
const screenDurationUtil = require('../util/screen-duration')
const projectDataUtil = require('../util/project-data')

const { AVERAGE_CHARS_IN_WORD } = require('../config/config')

class ProjectData {
/**
* @constructor
Expand Down Expand Up @@ -218,14 +227,18 @@ class ProjectData {
/**
* @param {Object} screen
* @returns {Object}
* @description Construct screen.
* @description Construct screen, adds methods to `screen` object.
*/
constructScreen (screen) {
const {
id, characterBasedDuration, compositionName, duration, extraVideoSecond, gifBigPath, gifPath, gifThumbnailPath,
hidden, iconAdjustable, isFull, maxDuration, order, path, tags, title, type, areas
} = screen

/**
* @namespace screen
* @description The screen object with it's methods.
*/
return {
id,
characterBasedDuration,
Expand All @@ -245,10 +258,81 @@ class ProjectData {
title,
type,
areas,
getAreas: () => {
return areas.map((area) => {
return this.constructArea(area)
})
/**
* @returns {Object}
* @description Maps through areas array and adds it's methods.
*/
getAreas: () => areas.map((area) => this.constructArea(area)),
/**
* @throws {ScreenHasVideoAreaError}
* @return {Object.characterBasedDuration}
* @description Checks if `screen` has video area, then throws error.
* Otherwise returns `characterBasedDuration`.
*/
isDurationAdjustable: () => {
const videoAreas = areas.filter((area) => area.type === 'video')

if (videoAreas.length > 0) {
throw new ScreenHasVideoAreaError('The screen has video area.')
}

return characterBasedDuration
},
/**
* @return {number}
* @description Calculates screen duration using screen duration utility.
* Detailed description can be found in screen duration util.
*/
calculateScreenDuration: () => screenDurationUtil.getScreenDuration(screen),
/**
* @returns {number}
* @description Filters ares to find only video ones.
* Checks if count of video areas is more than 0, then counts sum of `wordCount`s.
* Otherwise returns `maxDuration` or `duration`.
*/
getMaxPossibleDuration: () => {
const videoAreas = areas.filter((area) => area.type === 'video')

if (videoAreas.length > 0) {
return videoAreas.reduce((acc, videoArea) => acc + videoArea.wordCount, 0)
}

return maxDuration || duration
},
/**
* @param {number} duration - The new duration to set.
* @throws {CharacterBasedDurationError, DurationGreaterThanMaxPossibleError}
* @description Checks if `characterBasedDuration` is falsy, then throws error.
* If `duration` is more than maximum possible duration, then throws error.
* Otherwise sets `selectedDuration`.
*/
setDuration: function (duration) {
if (!characterBasedDuration) {
throw new CharacterBasedDurationError('Current screen\'s duration is not adjustable.')
}

if (duration > this.getMaxPossibleDuration()) {
throw new DurationGreaterThanMaxPossibleError('Given `value` is greater than maximum possible duration.')
}

this.selectedDuration = duration
},
/**
* @return {boolean}
* @description Checks if icon position is adjustable by double negation.
*/
isIconPositionAdjustable: () => iconAdjustable,
/**
* @throws {IconAdjustableError}
* @description Checks if icon position is not adjustable then throws error.
* Otherwise does `xor` bitwise operation with `iconAdjustable` and 3.
* Number `3` stands for converting 1->2 and 2->1.
*/
toggleIconPosition: function () {
if (!this.isIconPositionAdjustable()) {
throw new IconAdjustableError('Icon position is not adjustable.')
}
this.iconAdjustable ^= 3
}
}
}
Expand All @@ -271,6 +355,8 @@ class ProjectData {
area.value = text
this.patchProperties.push('screens')
}

result.getRecommendedCharacterCount = () => Math.floor(parseInt(wordCount) * AVERAGE_CHARS_IN_WORD)
}

if (area.type === 'image') {
Expand Down
1 change: 1 addition & 0 deletions src/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const PackageJson = require('../../package.json')
const config = {
API_HOST: 'https://api.renderforest.com',
API_PREFIX: '/api/v1',
AVERAGE_CHARS_IN_WORD: 5.5,
HTTP_DEFAULT_OPTIONS: {
method: 'GET',
json: true,
Expand Down
40 changes: 22 additions & 18 deletions src/util/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,27 @@
* LICENSE file in the root directory.
*/

class RenderforestError extends Error {
constructor (message) {
super()
this.message = message
this.name = this.constructor.name
}
}
const CUSTOM_ERRORS = [
'CharacterBasedDurationError',
'DurationGreaterThanMaxPossibleError',
'IconAdjustableError',
'MissingOrderError',
'RenderforestError',
'ScreenHasVideoAreaError',
'ScreenIdAlreadyExistsError'
]

class MissingOrderError extends Error {
constructor (message) {
super()
this.message = message
this.name = this.constructor.name
}
}
const ERRORS = CUSTOM_ERRORS.reduce((acc, className) => {
acc[className] = ({
[className]: class extends Error {
constructor (msg) {
super(msg)
this.name = this.constructor.name
}
}
})[className]

module.exports = {
RenderforestError,
MissingOrderError
}
return acc
}, {})

module.exports = ERRORS
27 changes: 19 additions & 8 deletions src/util/project-data.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const { ScreenIdAlreadyExistsError } = require('../util/error')

/**
* @param {Object} screen - The screen to normalize.
* @param {Number} index - The value to set.
* @returns {Object}
* @description Sets `screen.order` value to given `index`.
*/
function normalizeOrders (screen, index) {
const normalizeOrders = (screen, index) => {
screen.order = index
return screen
}
Expand All @@ -15,19 +17,15 @@ function normalizeOrders (screen, index) {
* @description Sort factory.
* Sorting function which sorts with given `prop`.
*/
function sortFactory (prop) {
return function (a, b) {
return parseInt(a[prop]) - parseInt(b[prop])
}
}
const sortFactory = (prop) => (a, b) => parseInt(a[prop]) - parseInt(b[prop])

/**
* @param {Array} screens - The screens array.
* @param {Object} newScreen - The screen to insert.
* @returns {Array}
* @description Inserts screen at the right order.
*/
function insertScreenAtOrder (screens, newScreen) {
const insertScreenAtOrder = (screens, newScreen) => {
if (screens.length === 0) {
return [newScreen]
}
Expand All @@ -53,14 +51,27 @@ function insertScreenAtOrder (screens, newScreen) {
}, [])
}

/**
* @param {Array} screens - The screens array.
* @param {Object} newScreen - The screen to insert.
* @return {boolean}
* @description Checks if there is already `screen` with given id, then returns `false`, otherwise `true`.
*/
const ifNewScreenIdExists = (screens, newScreen) =>
screens.findIndex(screen => screen.id === newScreen.id) < 0

/**
* @param {Array} screens - The screens array.
* @param {Object} newScreen - The screen to insert.
* @returns {Array}
* @description Inserting new screen, arranges screens by `screen.order`
* and normalize orders to have consequent numbers.
*/
function insertAndNormalizeOrder (screens, newScreen) {
const insertAndNormalizeOrder = (screens, newScreen) => {
if (!ifNewScreenIdExists(screens, newScreen)) {
throw new ScreenIdAlreadyExistsError('There is already one screen with current `screen.id`.')
}

return insertScreenAtOrder(screens, newScreen)
.sort(sortFactory('order'))
.map(normalizeOrders)
Expand Down
Loading

0 comments on commit 8f4392c

Please sign in to comment.