How to use intersection_point method in wpt

Best JavaScript code snippet using wpt

Game.ts

Source:Game.ts Github

copy

Full Screen

1import * as consts from "./Consts"2import { Server } from "socket.io"3import { Player } from "./Player";4import { Pong } from "./Pong";5import { GameMap } from "./GameMap";6import * as utils from "./../utils";7const top_bound : number = 10;8const bot_bound : number = consts.MAP_HEIGHT - 10;9const left_bound : number = 0;10const right_bound : number = consts.MAP_WIDTH;11export class Game {12 room_id : string;13 state : string;14 score : [number, number];15 score_limit : number;16 players : Player[];17 spectators : string[];18 pong : Pong;19 map : GameMap;20 frames_since_point : number;21 publicity : string;22 update_interval : any;23 countdown_timeout : any;24 invert : boolean;25 polling : boolean;26 constructor(room_id: any) {27 this.room_id = room_id;28 this.state = 'waiting-player';29 this.players = [];30 this.spectators = [];31 this.score = [0, 0];32 this.score_limit = 10;33 this.pong = new Pong();34 this.map = consts.original_map;35 this.frames_since_point = 0;36 this.publicity = "public";37 this.invert = false;38 this.polling = false;39 }40 spaceAvailable(username : string) {41 for (let player of this.players)42 if (player.real_name === username)43 return false;44 return (this.players.length <= 1);45 }46 kickPlayer(server : Server, id: any) {47 for (let player of this.players) {48 if (player.id === id) {49 server.to(this.room_id).emit("player-disconnect", this.players.indexOf(player));50 this.players.splice(this.players.indexOf(player), 1);51 this.reset();52 }53 }54 }55 reset() {56 for (let player of this.players)57 player.reset(this.players.length);58 this.state = "waiting-player";59 this.score = [0, 0];60 this.score_limit = 10;61 this.map = consts.original_map;62 delete this.pong;63 this.pong = new Pong();64 this.frames_since_point = 0;65 this.publicity = "public";66 this.invert = false;67 this.polling = false;68 }69 addSpectator(id : any) {70 this.spectators.push(id);71 }72 addPlayer(id: any, user : [string, string, boolean]) {73 for (let player of this.players)74 if (player.id === id)75 return ;76 if (this.players.length === 0)77 this.players.push(new Player("white", 1, id, user));78 else if (this.players.length === 1)79 this.players.push(new Player("white", 2, id, user));80 }81 setNewValue() {82 if (this.map.name !== "casino")83 return ;84 let rand : number = Math.floor(Math.random() * 11);85 if (rand === 0)86 this.pong.value = -1;87 else if (rand <= 4)88 this.pong.value = 1;89 else if (rand <= 7)90 this.pong.value = 2;91 else if (rand <= 9)92 this.pong.value = 3;93 else if (rand === 10)94 this.pong.value = 4;95 }96 increment_score() {97 if (!this.invert) {98 if (this.pong.value === -1 && this.score[1] > 0)99 this.score[1]--;100 else if (this.pong.value !== -1)101 this.score[0] += this.pong.value;102 }103 else {104 if (this.pong.value === -1 && this.score[0] > 0)105 this.score[0]--;106 else if (this.pong.value !== -1)107 this.score[1] += this.pong.value;108 }109 }110 over() : boolean {111 if (this.score[0] >= this.score_limit || this.score[1] >= this.score_limit)112 return true;113 return false;114 }115 scorePoint() : string {116 if (!this.invert)117 this.pong.relaunchPong("right");118 else119 this.pong.relaunchPong("left");120 this.setNewValue();121 this.frames_since_point = 0;122 return "relaunch";123 }124 checkCollisions(server : Server) : string {125 // Implement acceleration here126 if (this.frames_since_point === 0)127 this.pong.speed = consts.PONG_BASE_SPEED;128 else if (this.pong.speed < consts.PONG_MAX_SPEED) {129 if (this.pong.velocity[0] > 0)130 this.pong.velocity[0] += consts.PONG_ACCELERATION;131 else132 this.pong.velocity[0] -= consts.PONG_ACCELERATION;133 if (this.pong.velocity[1] > 0)134 this.pong.velocity[1] += consts.PONG_ACCELERATION;135 else136 this.pong.velocity[1] -= consts.PONG_ACCELERATION;137 this.pong.speed += consts.PONG_ACCELERATION * 2;138 }139 this.frames_since_point++;140 if (this.map.name === "city") {141 if (this.map.bumpers[0].checkCollision(this.pong)) {142 server.to(this.room_id).emit("bumper-hit", 0);143 return "none";144 }145 else if (this.map.bumpers[1].checkCollision(this.pong)) {146 server.to(this.room_id).emit("bumper-hit", 1);147 return "none";148 }149 }150 // ? collision with bounds151 if (this.pong.pos[1] < consts.TOP_BOUND || this.pong.pos[1] + this.pong.diameter > consts.BOT_BOUND) {152 if (this.pong.pos[1] < consts.TOP_BOUND) {153 this.pong.pos[1] = consts.TOP_BOUND + consts.MAP_HEIGHT * 0.005;154 }155 else if (this.pong.pos[1] + this.pong.diameter > consts.BOT_BOUND) {156 this.pong.pos[1] = consts.BOT_BOUND - this.pong.diameter - consts.MAP_HEIGHT * 0.005;157 }158 this.pong.velocity[1] *= -1;159 server.to(this.room_id).emit("wall-hit");160 }161 if (this.pong.velocity[0] > 0 && this.pong.pos[0] + this.pong.diameter > right_bound) {162 this.invert = false;163 return "relaunch";164 }165 else if (this.pong.velocity[0] < 0 && this.pong.pos[0] < left_bound) {166 this.invert = true;167 return "relaunch";168 }169 170 let player = (this.pong.pos[0] < consts.MAP_WIDTH / 2 ? this.players[0] : this.players[1]);171 let ball_points : [[number, number], [number, number], [number, number], [number, number]] = 172 [this.pong.up(), this.pong.right(), this.pong.down(), this.pong.left()];173 // ? collision with paddles174 for (let i = 0; i < 4; i++) {175 let angle : number = 0;176 let intersection_point : [number, number, string][] = [[-1, -1, "side"]]; // array of one element so that the variable is referenced in functions177 angle = this.collisionPaddle(player, intersection_point, ball_points[i]);178 179 if (intersection_point[0][0] !== -1) {180 server.to(this.room_id).emit("player-hit");181 let max_angle_percentage : number = Math.abs(angle) / (Math.PI * 3 / 12); // ? number that lets me add speed to acute angled shots182 // ? for bot / top collisions183 if (intersection_point[0][2] === "top" || intersection_point[0][2] === "bot") {184 if (intersection_point[0][2] === "top")185 this.pong.velocity[1] = (1 + consts.PONG_ACCELERATION_ACUTE_ANGLE * max_angle_percentage) * this.pong.speed * -Math.cos(angle);186 else if (intersection_point[0][2] === "bot")187 this.pong.velocity[1] = (1 + consts.PONG_ACCELERATION_ACUTE_ANGLE * max_angle_percentage) * this.pong.speed * Math.cos(angle);188 this.pong.velocity[0] = (1 + consts.PONG_ACCELERATION_ACUTE_ANGLE * max_angle_percentage) * this.pong.speed * -Math.sin(angle);189 }190 // ? invert velocity indexes for left / right collisions191 else if (intersection_point[0][2] === "side") {192 if (this.pong.pos[0] < this.map.width / 2)193 this.pong.velocity[0] = (1 + consts.PONG_ACCELERATION_ACUTE_ANGLE * max_angle_percentage) * this.pong.speed * Math.cos(angle);194 else195 this.pong.velocity[0] = (1 + consts.PONG_ACCELERATION_ACUTE_ANGLE * max_angle_percentage) * this.pong.speed * -Math.cos(angle);196 this.pong.velocity[1] = (1 + consts.PONG_ACCELERATION_ACUTE_ANGLE * max_angle_percentage) * this.pong.speed * -Math.sin(angle); 197 }198 }199 return "none"200 }201 return "none";202 }203 collisionPaddle(player : Player, intersection_point : [number, number, string][], ball_point : [number, number]) : number {204 let paddle_side_hit : [[number, number], [number, number]] = player.index === 1 ? 205 [player.rightUp(), player.rightDown()] : [player.leftUp(), player.leftDown()];206 let paddle_bot_hit : [[number, number], [number, number]] = [player.leftDown(), player.rightDown()];207 let paddle_top_hit : [[number, number], [number, number]] = [player.leftUp(), player.rightUp()];208 intersection_point[0] = utils.getLineIntersection(ball_point, this.pong.ballMoves(ball_point), paddle_side_hit[0], paddle_side_hit[1]);209 intersection_point[0][2] = "side";210 if (intersection_point[0][0] !== -1)211 return utils.relativeIntersection(intersection_point[0], paddle_side_hit[0], paddle_side_hit[1]);212 213 // ? Multiplying velocity vector by 3 for better precision in bot/top intersection214 intersection_point[0] = utils.getLineIntersection(ball_point, this.pong.ballMoves(ball_point), paddle_bot_hit[0], paddle_bot_hit[1]);215 intersection_point[0][2] = "bot";216 if (intersection_point[0][0] !== -1)217 return utils.relativeIntersection(intersection_point[0], paddle_bot_hit[0], paddle_bot_hit[1]);218 219 intersection_point[0] = utils.getLineIntersection(ball_point, this.pong.ballMoves(ball_point), paddle_top_hit[0], paddle_top_hit[1]);220 intersection_point[0][2] = "top";221 if (intersection_point[0][0] !== -1)222 return utils.relativeIntersection(intersection_point[0], paddle_top_hit[0], paddle_top_hit[1]);223 224 return 0;225 }...

Full Screen

Full Screen

controllers.js

Source:controllers.js Github

copy

Full Screen

1// import * as THREE from 'three';2import * as PHYSICS from './physics.js';3import { params, redraw_supports, redraw_beam, controls, box, SFD, BMD, renderer } from './index.js';4export const handleBeamSelectStart = (object, controller) => {5 // console.log(controller)6 if (renderer.xr.isPresenting) {7 if (controller !== undefined) {8 controller.selected = object;9 const intersection_point = controls.raycaster.intersectObject(object)[0].point;10 controller.select_start_position = intersection_point;11 }12 }13}14export const handleBeamIntersection = (object) => {15 if (renderer.xr.isPresenting) {16 // console.log(controls.vrControls.controllers.right.selected)17 let intersection_point;18 let controller;19 if (controls.vrControls.controllers.left.selected === object) {20 intersection_point = controls.raycaster.intersectObject(object)[0].point;21 controller = controls.vrControls.controllers.left;22 } else if (controls.vrControls.controllers.right.selected === object) {23 intersection_point = controls.raycaster.intersectObject(object)[0].point;24 controller = controls.vrControls.controllers.right;25 }26 if (intersection_point !== undefined) {27 params.displacement.subVectors(controller.select_start_position, intersection_point); // 28 params.load_position = intersection_point.x + params.length / 2.;29 params.displacement.y = Math.sign(params.displacement.y) * Math.min(Math.abs(params.displacement.y), PHYSICS.max_displacement);30 console.log(params.load_position);//,params.displacement.x,controller.select_start_position.x,intersection_point.x)31 const supportHaptic = 'hapticActuators' in controller.gamepad && controller.gamepad.hapticActuators != null && controller.gamepad.hapticActuators.length > 0;32 if ( supportHaptic ) {33 const intensity = Math.abs(PHYSICS.P/PHYSICS.P_max);34 controller.gamepad.hapticActuators[ 0 ].pulse( intensity, 100 );35 }36 37 }38 }39}40export const handleBeamSelectEnd = (object, controller) => {41 if (renderer.xr.isPresenting) {42 controller.select_start_position = undefined;43 controller.selected = undefined;44 params.displacement = new THREE.Vector3();45 }46}47export const handleLeftSupportSelectStart = (object, controller) => {48 if (params.left == 'Pin') { params.left = 'Fixed' }49 else if (params.left == 'Fixed') { params.left = 'Free' }50 else if (params.left == 'Free') { params.left = 'Pin' }51 redraw_supports();52}53export const handleRightSupportSelectStart = (object, controller) => {54 if (params.right == 'Pin') { params.right = 'Fixed' }55 else if (params.right == 'Fixed') { params.right = 'Free' }56 else if (params.right == 'Free') { params.right = 'Pin' }57 redraw_supports();58}59export const handleSupportSelectEnd = (object, controller) => {60 // console.log(object)61 // params.displacement = 0;62}63export const handleColorSelectStart = (object, controller) => {64 if (params.colour_by == 'Bending Moment') {65 params.colour_by = 'Shear Force';66 box.remove(BMD);67 box.add(SFD);68 }69 else if (params.colour_by == 'Shear Force') {70 params.colour_by = 'Bending Moment';71 box.remove(SFD);72 box.add(BMD);73 }74 redraw_beam();75}76export const handleColorSelectEnd = (object, controller) => {77 // do nothing!...

Full Screen

Full Screen

2d_line_intersection.js

Source:2d_line_intersection.js Github

copy

Full Screen

1// computational geometry | 2D line intersecton | JavaScript2function intersection_by_points(x1, y1, x2, y2, x3, y3, x4, y4) {3 var x12 = x1 - x2;4 var x34 = x3 - x4;5 var y12 = y1 - y2;6 var y34 = y3 - y4;7 var c = x12 * y34 - y12 * x34;8 var a = x1 * y2 - y1 * x2;9 var b = x3 * y4 - y3 * x4;10 var x = (a * x34 - b * x12) / c;11 var y = (a * y34 - b * y12) / c;12 // Keeping points integers. Change according to requirement13 x = parseInt(x);14 y = parseInt(y);15 return { x: x, y: y };16}17// Line segments defined by 2 points a-b and c-d18function intersection_by_vectors(vec1, vec2, vec3, vec4) {19 return intersection_by_points(20 vec1["x"],21 vec1["y"],22 vec2["x"],23 vec2["y"],24 vec3["x"],25 vec3["y"],26 vec4["x"],27 vec4["y"]28 );29}30// Accepts line in Ax+By = C format31function intersection_by_line_euqation(line1, line2) {32 var A1 = line1["A"];33 var B1 = line1["B"];34 var C1 = line1["C"];35 var A2 = line2["A"];36 var B2 = line2["B"];37 var C2 = line2["C"];38 var delta = A1 * B2 - A2 * B1;39 if (delta === 0) console.log("Lines are parallel");40 var x = (B2 * C1 - B1 * C2) / delta;41 var y = (A1 * C2 - A2 * C1) / delta;42 // Keeping points integers. Change according to requirement43 x = parseInt(x);44 y = parseInt(y);45 return { x: x, y: y };46}47// Driver Program48function main() {49 // 3x + 4y = 150 var line1 = { A: 3, B: 4, C: 1 };51 // 2x + 5y = 352 var line2 = { A: 2, B: 5, C: 3 };53 var intersection_point = intersection_by_line_euqation(line1, line2);54 console.log("Test using line equation");55 console.log(56 `Lines intersect at x:${intersection_point["x"]}, y:${57 intersection_point["y"]58 }`59 );60 console.log("Test using points");61 intersection_point = intersection_by_vectors(62 { x: 2, y: 5 },63 { x: 5, y: 3 },64 { x: 7, y: 4 },65 { x: 1, y: 6 }66 );67 console.log(68 `Lines intersect at x:${intersection_point["x"]}, y:${69 intersection_point["y"]70 }`71 );72}...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var point1 = new wpt.Point(1,2);3var point2 = new wpt.Point(3,4);4var point3 = new wpt.Point(5,6);5var point4 = new wpt.Point(7,8);6var intersection_point = wpt.intersection_point(point1,point2,point3,point4);7console.log(intersection_point);8var wpt = require('wpt');9var point1 = new wpt.Point(1,2);10var point2 = new wpt.Point(3,4);11var point3 = new wpt.Point(5,6);12var point4 = new wpt.Point(7,8);13var intersection_point = wpt.intersection_point(point1,point2,point3,point4);14console.log(intersection_point);15var wpt = require('wpt');16var point1 = new wpt.Point(1,2);17var point2 = new wpt.Point(3,4);18var point3 = new wpt.Point(5,6);19var point4 = new wpt.Point(7,8);20var intersection_point = wpt.intersection_point(point1,point2,point3,point4);21console.log(intersection_point);22var wpt = require('wpt');23var point1 = new wpt.Point(1,2);24var point2 = new wpt.Point(3,4);25var point3 = new wpt.Point(5,6);26var point4 = new wpt.Point(7,8);27var intersection_point = wpt.intersection_point(point1,point2,point3,point4);28console.log(intersection_point);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('./wpt.js');2var a = {x: 0, y: 0};3var b = {x: 5, y: 5};4var c = {x: 5, y: 0};5var d = {x: 0, y: 5};6console.log(wpt.intersection_point(a, b, c, d));7var wpt = require('./wpt.js');8var a = {x: 0, y: 0};9var b = {x: 5, y: 5};10var c = {x: 5, y: 0};11var d = {x: 0, y: 5};12console.log(wpt.intersection_point(a, b, c, d));13var wpt = require('./wpt.js');14var a = {x: 0, y: 0};15var b = {x: 5, y: 5};16var c = {x: 5, y: 0};17var d = {x: 0, y: 5};18console.log(wpt.intersection_point(a, b, c, d));19var wpt = require('./wpt.js');20var a = {x: 0, y: 0};21var b = {x: 5, y: 5};22var c = {x: 5, y: 0};23var d = {x: 0, y: 5};24console.log(wpt.intersection_point(a, b, c, d));25var wpt = require('./wpt.js');26var a = {x: 0, y: 0};27var b = {x: 5,

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt.js');2var point1 = new wpt(0,0);3var point2 = new wpt(5,5);4var point3 = new wpt(5,0);5var point4 = new wpt(0,5);6var intersection_point = point1.intersection_point(point2, point3, point4);7console.log(intersection_point);8var wpt = require('wpt.js');9var point1 = new wpt(0,0);10var point2 = new wpt(5,5);11var point3 = new wpt(5,0);12var point4 = new wpt(0,5);13var intersection_point = point1.intersection_point(point2, point3, point4);14console.log(intersection_point);15var wpt = require('wpt.js');16var point1 = new wpt(0,0);17var point2 = new wpt(5,5);18var point3 = new wpt(5,0);19var point4 = new wpt(0,5);20var intersection_point = point1.intersection_point(point2, point3, point4);21console.log(intersection_point);22var wpt = require('wpt.js');23var point1 = new wpt(0,0);24var point2 = new wpt(5,5);25var point3 = new wpt(5,0);26var point4 = new wpt(0,5);27var intersection_point = point1.intersection_point(point2, point3, point4);28console.log(intersection_point);29var wpt = require('wpt.js');30var point1 = new wpt(0,0);31var point2 = new wpt(5,5);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var wpt = new WebPageTest('www.webpagetest.org');3 if (err) return console.error(err);4 wpt.getTestResults(data.data.testId, function(err, data) {5 if (err) return console.error(err);6 var wpt = new WebPageTest('www.webpagetest.org');7 var test = wpt.getTest(data.data.id);8 test.getWaterfallImage(function(err, data) {9 if (err) return console.error(err);10 var intersection_point = test.intersection_point(0.5, 0.5, 0.5, 0.5);11 console.log(intersection_point);12 });13 });14});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt.js');2var wpt = new wpt();3var point1 = {x: 1, y: 2};4var point2 = {x: 3, y: 4};5var point3 = {x: 5, y: 6};6var point4 = {x: 7, y: 8};7var intersection = wpt.intersection_point(point1, point2, point3, point4);8console.log(intersection);9var wpt = require('wpt.js');10var wpt = new wpt();11var point1 = {x: 1, y: 2};12var point2 = {x: 3, y: 4};13var point3 = {x: 5, y: 6};14var point4 = {x: 7, y: 8};15var intersection = wpt.intersection_point(point1, point2, point3, point4);16console.log(intersection);17var wpt = require('wpt.js');18var wpt = new wpt();19var point1 = {x: 1, y: 2};20var point2 = {x: 3, y: 4};21var point3 = {x: 5, y: 6};22var point4 = {x: 7, y: 8};23var intersection = wpt.intersection_point(point1, point2, point3, point4);24console.log(intersection);25var wpt = require('wpt.js');26var wpt = new wpt();27var point1 = {x: 1, y: 2};28var point2 = {x: 3, y: 4};29var point3 = {x: 5, y: 6};30var point4 = {x: 7, y: 8};31var intersection = wpt.intersection_point(point1, point2, point3, point4);32console.log(intersection);33var wpt = require('wpt.js');

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var point = wpt.intersection_point(0,0, 1,1, 0,1, 1,0);3console.log(point.x, point.y);4var wpt = require('wpt');5var point = wpt.intersection_point(0,0, 1,1, 0,1, 1,0);6console.log(point.x, point.y);7var wpt = require('wpt');8var point = wpt.segment_intersection(0,0, 1,1, 0,1, 1,0);9console.log(point.x, point.y);10var wpt = require('wpt');11var point = wpt.segment_intersection(0,0, 1,1, 0,1, 1,0);12console.log(point.x, point.y);13var wpt = require('wpt');14var result = wpt.point_in_polygon(0,0, [[0,0],[1,0],[1,1],[0,1]]);15console.log(result);16var wpt = require('wpt');17var result = wpt.point_in_polygon(0,0, [[0,0],[1,0],[1,1],[0,1]]);18console.log(result);19var wpt = require('wpt');20var result = wpt.polygon_area([[0,0],[1,0],[1,1],[0,1]]);21console.log(result);22var wpt = require('wpt');23var result = wpt.polygon_area([[0,0],[1,0],[1,1],[0,1]]);24console.log(result);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var wptObject = new wpt('Your API Key');3var lat1 = 40.7127;4var lon1 = -74.0059;5var lat2 = 34.0522;6var lon2 = -118.2437;7wptObject.intersection_point(lat1, lon1, lat2, lon2, function(err, data) {8 if (err) {9 console.log(err);10 } else {11 console.log(data);12 }13});14var wpt = require('wpt');15var wptObject = new wpt('Your API Key');16var lat = 37.7245;17var lon = -95.9623;18wptObject.location(lat, lon, function(err, data) {19 if (err) {20 console.log(err);21 } else {22 console.log(data);23 }24});25var wpt = require('wpt');26var wptObject = new wpt('Your API Key');27var lat = 40.7127;28var lon = -74.0059;29wptObject.nearest_location(lat, lon, function(err, data) {30 if (err) {31 console.log(err);32 } else {33 console.log(data);34 }35});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var wp = wptools.page('Eiffel Tower');3wp.intersect('Paris', function(err, res) {4 console.log(res);5});6{ lat: 48.858225, lon: 2.294359 }

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var utils = require('utils');3var test = require('test');4var fs = require('fs');5var system = require('system');6var wpt = new WebPageTest('www.webpagetest.org');7var options = {

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var wp = new wptools('Eiffel Tower');3wp.intersect('Paris', function(err, res){4 console.log(res);5});6### `wp = new wptools(page, [options])`7### `wp.get([options], callback)`8### `wp.raw([options], callback)`9### `wp.html([options], callback)`10### `wp.text([options], callback)`11### `wp.categories([options], callback)`

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful