[RELEASE] Impossible POT Challenge

All about the past, current and future webteases and the art of webteasing in general.
---
Post Reply
kHaos86
Curious Newbie
Curious Newbie
Posts: 2
Joined: Tue Mar 31, 2020 7:31 am

[RELEASE] Impossible POT Challenge

Post by kHaos86 »

Hi.

Here's the link : https://milovana.com/webteases/showtease.php?id=45102

I thought it was time for a new POT challenge. :lol:
This thread is for comments, suggestions and bug reports.
Please leave your feedback and suggestions.
User avatar
Takenaga
Explorer At Heart
Explorer At Heart
Posts: 456
Joined: Sun Dec 04, 2011 12:58 pm
Gender: Male
Sexual Orientation: Straight
Location: Netherlands

Re: [RELEASE] Impossible POT Challenge

Post by Takenaga »

Thanks for your effort! I love POT (but it's a bit hard to do by yourself) and I will give your tease a try as soon as possible.
Try GuideMe or TeaseMe to play Milovana Teases offline or create your own offline teases with highres images and videos... don't forget to support milovana and rate the online teases!
User avatar
Dawn_of_Dark
Explorer
Explorer
Posts: 30
Joined: Mon Oct 23, 2017 2:30 pm
Gender: Male
Sexual Orientation: Straight
I am a: Switch

Re: [RELEASE] Impossible POT Challenge

Post by Dawn_of_Dark »

I think it's a really well done tease, specifically the text.

However, I do think it's too long, even for an "impossible" challenge. Each scene drags on too long, especially since each picture mostly contains only a sentence or two. Maybe only 5 seconds each picture is enough imo.

The overall length of the tease is also admittedly impossibly long. I had the tease runs by itself while looking at other teases/porn and switch back and forth (which is I usually do), and I got to the "end" after like, an hour and a half, or something like that.

I think your idea was good and again, the text was splendid, but the length of the whole thing will make most of your hard work go unread with most of the users here.
kHaos86
Curious Newbie
Curious Newbie
Posts: 2
Joined: Tue Mar 31, 2020 7:31 am

Re: [RELEASE] Impossible POT Challenge

Post by kHaos86 »

Thanks for your feedback

yeah, maybe it's pretty hard to complete the challenge on the first trys :look:
The tease contains 10 picsets and the rules change for the last 3 sets. In the tease, the pages change after 30 seconds.
In the beginning I thought about splitting it in two parts, but that would worsen the experience.

I have a couple of other ideas I want to implement in teases.
But I think I will create a shorter and simpler version of the tease. :smile:
User avatar
Khalsissy
Explorer
Explorer
Posts: 20
Joined: Mon Nov 04, 2019 8:26 pm
Gender: Male
Sexual Orientation: Bisexual/Bi-Curious
I am a: Submissive

Re: [RELEASE] Impossible POT Challenge

Post by Khalsissy »

Mistype in the very beginning:
1. You must do full and thigt strokes.
Если вам нравятся мои работы - поддержите меня на https://www.patreon.com/KhalSissy
Попробуйте другие мои тизы: https://milovana.com/webteases/?author=105383
---------------
If you like what I'm doing - come and support me at https://www.patreon.com/KhalSissy
Try out another teases created by me https://milovana.com/webteases/?author=105383
Achatius
Explorer
Explorer
Posts: 37
Joined: Sun Aug 02, 2015 11:10 am
Gender: Male
Sexual Orientation: Straight
I am a: None of the above

Re: [RELEASE] Impossible POT Challenge

Post by Achatius »

It was a Totm... worthy for remastered. is khaos86 still active?
Ghingis
Explorer At Heart
Explorer At Heart
Posts: 177
Joined: Mon Oct 24, 2011 4:55 pm

Re: [RELEASE] Impossible POT Challenge

Post by Ghingis »

The thing is it is not so easy to continue after a while, this might help if you have a handy..

* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art

How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)

If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.

Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.

Code: Select all

// ==UserScript==
// @name         EOS
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://oeos.art/?id=*
// @icon         https://www.google.com/s2/favicons?domain=oeos.art
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    const maxStrokeSpeed = 400;
    const maxStrokeLength = 190;
    const apiKey = 'YOUR_HANDY_API_KEY'; // api key
    const api = "https://www.handyfeeling.com/api/handy/v2";
    let lastSpeed = 0;

    const sendRequest = (url, data, verb, onResponse) => {

        let myHeaders = new Headers();
        if (verb.trim().toLowerCase() !== 'option'){
            myHeaders.append('X-Connection-Key', apiKey);
            myHeaders.append('Content-Type', 'application/json');
            myHeaders.append('Accept', 'application/json');
        }

        const options = {
            method: verb,
            headers: myHeaders,
            mode: 'cors',
        }

        if (data) {
            options.body = JSON.stringify(data);
        }

        console.log(url, 'request: ', options);

        fetch(url, options)
            .then(function(response) {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json().then((r)=>{
                console.log('response: ', r);
                onResponse(r);
            });
        })
    }

    sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => {
        sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => {
            sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{
                console.log('handy set');
            });
        });
    });

    /**
     * Calculates the stroke speed and distance from the specified beats per second.
     *
     * Lookup Table
     * ====================
     * Speed / Stroke = BPS
     * 400 / 80  = 5
     * 400 / 100 = 4
     * 400 / 133 = 3
     * 400 / 200 = 2
     * 300 / 200 = 1.5
     * 200 / 200 = 1
     * 100 / 200 = 0.5
     * 50  / 200 = 0.25
     */
    function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) {
        maxSpeed = Math.min(maxStrokeSpeed, maxSpeed);
        maxLength = Math.min(maxStrokeLength, maxLength);
        let speed = maxSpeed;
        let length = maxLength;
        const fastestBPS = maxSpeed / maxLength;

        // Decrease stroke speed to increase BPS
        if (bps < fastestBPS) {
            speed = maxLength * bps;
        }

        // Shorten stroke distance to increase BPS
        if (bps > fastestBPS) {
            length = maxSpeed / bps;
        }

        return {
            speed,
            stroke: length,
        };
    }

    function changeSpeed(newState) {
        sendRequest(api + "/hamp/state", null, 'GET',(response)=>{
            console.log('state',response);
            if (response.state !== 2){
                sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{
                    console.log('start')
                    sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                        console.log(request.speed)
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                    });
                });
            } else {
                if (lastSpeed !== newState.speed){
                    if (lastSpeed > newState.speed){
                        sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                        });
                    } else {
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed));
                        });
                    }
                }
            }

            lastSpeed = newState.speed;
        });
    }

    const mainWrapperCallback = (records, ob) => {
        records.forEach((record)=>{
            if (record.target.id === 'oeos-sounds'){
                const data = record.target.querySelector('data');
                if (data){
                    const match = data.value.match(/([1-9].+)bpm/);
                    if (match){
                        const bpm = parseInt(match[1],10);
                        console.log('bpm',bpm);
                        const newState = getStrokeSpeedAndDistance(bpm/60);
                        changeSpeed(newState);
                    } else {
                        const bpsMatch = data.value.match(/([1-9].+)bps/);
                        if (bpsMatch){
                            const bps = parseInt(bpsMatch[1],10);
                            const newState = getStrokeSpeedAndDistance(bps);
                            changeSpeed(newState);
                        } else {
                            const bpsMatch = data.value.match(/([1-9].+)ps/);
                            if (bpsMatch){
                                const bps = parseInt(bpsMatch[1],10);
                                const newState = getStrokeSpeedAndDistance(bps);
                                changeSpeed(newState);
                            }
                        }
                    }
                } else {
                    // remove the next 3 lines
                    sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{
                        console.log('stop', response);
                    });
                }
            }
        });
    };

    const mainWrapper = document.querySelector('.v-main__wrap');
    // Create an observer instance linked to the callback function
    const wrapperObserver = new MutationObserver(mainWrapperCallback);

    // Start observing the target node for configured mutations
    wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true });
})();
Achatius
Explorer
Explorer
Posts: 37
Joined: Sun Aug 02, 2015 11:10 am
Gender: Male
Sexual Orientation: Straight
I am a: None of the above

Re: [RELEASE] Impossible POT Challenge

Post by Achatius »

Ghingis wrote: Sat Dec 04, 2021 3:50 pm The thing is it is not so easy to continue after a while, this might help if you have a handy..

* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art

How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)

If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.

Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.

Code: Select all

// ==UserScript==
// @name         EOS
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://oeos.art/?id=*
// @icon         https://www.google.com/s2/favicons?domain=oeos.art
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    const maxStrokeSpeed = 400;
    const maxStrokeLength = 190;
    const apiKey = 'YOUR_HANDY_API_KEY'; // api key
    const api = "https://www.handyfeeling.com/api/handy/v2";
    let lastSpeed = 0;

    const sendRequest = (url, data, verb, onResponse) => {

        let myHeaders = new Headers();
        if (verb.trim().toLowerCase() !== 'option'){
            myHeaders.append('X-Connection-Key', apiKey);
            myHeaders.append('Content-Type', 'application/json');
            myHeaders.append('Accept', 'application/json');
        }

        const options = {
            method: verb,
            headers: myHeaders,
            mode: 'cors',
        }

        if (data) {
            options.body = JSON.stringify(data);
        }

        console.log(url, 'request: ', options);

        fetch(url, options)
            .then(function(response) {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json().then((r)=>{
                console.log('response: ', r);
                onResponse(r);
            });
        })
    }

    sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => {
        sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => {
            sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{
                console.log('handy set');
            });
        });
    });

    /**
     * Calculates the stroke speed and distance from the specified beats per second.
     *
     * Lookup Table
     * ====================
     * Speed / Stroke = BPS
     * 400 / 80  = 5
     * 400 / 100 = 4
     * 400 / 133 = 3
     * 400 / 200 = 2
     * 300 / 200 = 1.5
     * 200 / 200 = 1
     * 100 / 200 = 0.5
     * 50  / 200 = 0.25
     */
    function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) {
        maxSpeed = Math.min(maxStrokeSpeed, maxSpeed);
        maxLength = Math.min(maxStrokeLength, maxLength);
        let speed = maxSpeed;
        let length = maxLength;
        const fastestBPS = maxSpeed / maxLength;

        // Decrease stroke speed to increase BPS
        if (bps < fastestBPS) {
            speed = maxLength * bps;
        }

        // Shorten stroke distance to increase BPS
        if (bps > fastestBPS) {
            length = maxSpeed / bps;
        }

        return {
            speed,
            stroke: length,
        };
    }

    function changeSpeed(newState) {
        sendRequest(api + "/hamp/state", null, 'GET',(response)=>{
            console.log('state',response);
            if (response.state !== 2){
                sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{
                    console.log('start')
                    sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                        console.log(request.speed)
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                    });
                });
            } else {
                if (lastSpeed !== newState.speed){
                    if (lastSpeed > newState.speed){
                        sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                        });
                    } else {
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed));
                        });
                    }
                }
            }

            lastSpeed = newState.speed;
        });
    }

    const mainWrapperCallback = (records, ob) => {
        records.forEach((record)=>{
            if (record.target.id === 'oeos-sounds'){
                const data = record.target.querySelector('data');
                if (data){
                    const match = data.value.match(/([1-9].+)bpm/);
                    if (match){
                        const bpm = parseInt(match[1],10);
                        console.log('bpm',bpm);
                        const newState = getStrokeSpeedAndDistance(bpm/60);
                        changeSpeed(newState);
                    } else {
                        const bpsMatch = data.value.match(/([1-9].+)bps/);
                        if (bpsMatch){
                            const bps = parseInt(bpsMatch[1],10);
                            const newState = getStrokeSpeedAndDistance(bps);
                            changeSpeed(newState);
                        } else {
                            const bpsMatch = data.value.match(/([1-9].+)ps/);
                            if (bpsMatch){
                                const bps = parseInt(bpsMatch[1],10);
                                const newState = getStrokeSpeedAndDistance(bps);
                                changeSpeed(newState);
                            }
                        }
                    }
                } else {
                    // remove the next 3 lines
                    sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{
                        console.log('stop', response);
                    });
                }
            }
        });
    };

    const mainWrapper = document.querySelector('.v-main__wrap');
    // Create an observer instance linked to the callback function
    const wrapperObserver = new MutationObserver(mainWrapperCallback);

    // Start observing the target node for configured mutations
    wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true });
})();
Thx a lot! Are you able to edit it?
Ghingis
Explorer At Heart
Explorer At Heart
Posts: 177
Joined: Mon Oct 24, 2011 4:55 pm

Re: [RELEASE] Impossible POT Challenge

Post by Ghingis »

Achatius wrote: Sun Dec 19, 2021 11:17 am
Ghingis wrote: Sat Dec 04, 2021 3:50 pm The thing is it is not so easy to continue after a while, this might help if you have a handy..

* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art

How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)

If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.

Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.

Code: Select all

// ==UserScript==
// @name         EOS
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://oeos.art/?id=*
// @icon         https://www.google.com/s2/favicons?domain=oeos.art
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    const maxStrokeSpeed = 400;
    const maxStrokeLength = 190;
    const apiKey = 'YOUR_HANDY_API_KEY'; // api key
    const api = "https://www.handyfeeling.com/api/handy/v2";
    let lastSpeed = 0;

    const sendRequest = (url, data, verb, onResponse) => {

        let myHeaders = new Headers();
        if (verb.trim().toLowerCase() !== 'option'){
            myHeaders.append('X-Connection-Key', apiKey);
            myHeaders.append('Content-Type', 'application/json');
            myHeaders.append('Accept', 'application/json');
        }

        const options = {
            method: verb,
            headers: myHeaders,
            mode: 'cors',
        }

        if (data) {
            options.body = JSON.stringify(data);
        }

        console.log(url, 'request: ', options);

        fetch(url, options)
            .then(function(response) {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json().then((r)=>{
                console.log('response: ', r);
                onResponse(r);
            });
        })
    }

    sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => {
        sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => {
            sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{
                console.log('handy set');
            });
        });
    });

    /**
     * Calculates the stroke speed and distance from the specified beats per second.
     *
     * Lookup Table
     * ====================
     * Speed / Stroke = BPS
     * 400 / 80  = 5
     * 400 / 100 = 4
     * 400 / 133 = 3
     * 400 / 200 = 2
     * 300 / 200 = 1.5
     * 200 / 200 = 1
     * 100 / 200 = 0.5
     * 50  / 200 = 0.25
     */
    function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) {
        maxSpeed = Math.min(maxStrokeSpeed, maxSpeed);
        maxLength = Math.min(maxStrokeLength, maxLength);
        let speed = maxSpeed;
        let length = maxLength;
        const fastestBPS = maxSpeed / maxLength;

        // Decrease stroke speed to increase BPS
        if (bps < fastestBPS) {
            speed = maxLength * bps;
        }

        // Shorten stroke distance to increase BPS
        if (bps > fastestBPS) {
            length = maxSpeed / bps;
        }

        return {
            speed,
            stroke: length,
        };
    }

    function changeSpeed(newState) {
        sendRequest(api + "/hamp/state", null, 'GET',(response)=>{
            console.log('state',response);
            if (response.state !== 2){
                sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{
                    console.log('start')
                    sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                        console.log(request.speed)
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                    });
                });
            } else {
                if (lastSpeed !== newState.speed){
                    if (lastSpeed > newState.speed){
                        sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                        });
                    } else {
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed));
                        });
                    }
                }
            }

            lastSpeed = newState.speed;
        });
    }

    const mainWrapperCallback = (records, ob) => {
        records.forEach((record)=>{
            if (record.target.id === 'oeos-sounds'){
                const data = record.target.querySelector('data');
                if (data){
                    const match = data.value.match(/([1-9].+)bpm/);
                    if (match){
                        const bpm = parseInt(match[1],10);
                        console.log('bpm',bpm);
                        const newState = getStrokeSpeedAndDistance(bpm/60);
                        changeSpeed(newState);
                    } else {
                        const bpsMatch = data.value.match(/([1-9].+)bps/);
                        if (bpsMatch){
                            const bps = parseInt(bpsMatch[1],10);
                            const newState = getStrokeSpeedAndDistance(bps);
                            changeSpeed(newState);
                        } else {
                            const bpsMatch = data.value.match(/([1-9].+)ps/);
                            if (bpsMatch){
                                const bps = parseInt(bpsMatch[1],10);
                                const newState = getStrokeSpeedAndDistance(bps);
                                changeSpeed(newState);
                            }
                        }
                    }
                } else {
                    // remove the next 3 lines
                    sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{
                        console.log('stop', response);
                    });
                }
            }
        });
    };

    const mainWrapper = document.querySelector('.v-main__wrap');
    // Create an observer instance linked to the callback function
    const wrapperObserver = new MutationObserver(mainWrapperCallback);

    // Start observing the target node for configured mutations
    wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true });
})();
Thx a lot! Are you able to edit it?
You are welcome, I'm not sure what do you want to edit on this, but anyone could do it.
But I can change things, if you have recommendations.
Achatius
Explorer
Explorer
Posts: 37
Joined: Sun Aug 02, 2015 11:10 am
Gender: Male
Sexual Orientation: Straight
I am a: None of the above

Re: [RELEASE] Impossible POT Challenge

Post by Achatius »

Ghingis wrote: Mon Dec 20, 2021 12:07 am
Achatius wrote: Sun Dec 19, 2021 11:17 am
Ghingis wrote: Sat Dec 04, 2021 3:50 pm The thing is it is not so easy to continue after a while, this might help if you have a handy..

* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art

How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)

If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.

Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.

Code: Select all

// ==UserScript==
// @name         EOS
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://oeos.art/?id=*
// @icon         https://www.google.com/s2/favicons?domain=oeos.art
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    const maxStrokeSpeed = 400;
    const maxStrokeLength = 190;
    const apiKey = 'YOUR_HANDY_API_KEY'; // api key
    const api = "https://www.handyfeeling.com/api/handy/v2";
    let lastSpeed = 0;

    const sendRequest = (url, data, verb, onResponse) => {

        let myHeaders = new Headers();
        if (verb.trim().toLowerCase() !== 'option'){
            myHeaders.append('X-Connection-Key', apiKey);
            myHeaders.append('Content-Type', 'application/json');
            myHeaders.append('Accept', 'application/json');
        }

        const options = {
            method: verb,
            headers: myHeaders,
            mode: 'cors',
        }

        if (data) {
            options.body = JSON.stringify(data);
        }

        console.log(url, 'request: ', options);

        fetch(url, options)
            .then(function(response) {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json().then((r)=>{
                console.log('response: ', r);
                onResponse(r);
            });
        })
    }

    sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => {
        sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => {
            sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{
                console.log('handy set');
            });
        });
    });

    /**
     * Calculates the stroke speed and distance from the specified beats per second.
     *
     * Lookup Table
     * ====================
     * Speed / Stroke = BPS
     * 400 / 80  = 5
     * 400 / 100 = 4
     * 400 / 133 = 3
     * 400 / 200 = 2
     * 300 / 200 = 1.5
     * 200 / 200 = 1
     * 100 / 200 = 0.5
     * 50  / 200 = 0.25
     */
    function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) {
        maxSpeed = Math.min(maxStrokeSpeed, maxSpeed);
        maxLength = Math.min(maxStrokeLength, maxLength);
        let speed = maxSpeed;
        let length = maxLength;
        const fastestBPS = maxSpeed / maxLength;

        // Decrease stroke speed to increase BPS
        if (bps < fastestBPS) {
            speed = maxLength * bps;
        }

        // Shorten stroke distance to increase BPS
        if (bps > fastestBPS) {
            length = maxSpeed / bps;
        }

        return {
            speed,
            stroke: length,
        };
    }

    function changeSpeed(newState) {
        sendRequest(api + "/hamp/state", null, 'GET',(response)=>{
            console.log('state',response);
            if (response.state !== 2){
                sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{
                    console.log('start')
                    sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                        console.log(request.speed)
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                    });
                });
            } else {
                if (lastSpeed !== newState.speed){
                    if (lastSpeed > newState.speed){
                        sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
                        });
                    } else {
                        sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{
                            console.log(request.speed)
                            sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed));
                        });
                    }
                }
            }

            lastSpeed = newState.speed;
        });
    }

    const mainWrapperCallback = (records, ob) => {
        records.forEach((record)=>{
            if (record.target.id === 'oeos-sounds'){
                const data = record.target.querySelector('data');
                if (data){
                    const match = data.value.match(/([1-9].+)bpm/);
                    if (match){
                        const bpm = parseInt(match[1],10);
                        console.log('bpm',bpm);
                        const newState = getStrokeSpeedAndDistance(bpm/60);
                        changeSpeed(newState);
                    } else {
                        const bpsMatch = data.value.match(/([1-9].+)bps/);
                        if (bpsMatch){
                            const bps = parseInt(bpsMatch[1],10);
                            const newState = getStrokeSpeedAndDistance(bps);
                            changeSpeed(newState);
                        } else {
                            const bpsMatch = data.value.match(/([1-9].+)ps/);
                            if (bpsMatch){
                                const bps = parseInt(bpsMatch[1],10);
                                const newState = getStrokeSpeedAndDistance(bps);
                                changeSpeed(newState);
                            }
                        }
                    }
                } else {
                    // remove the next 3 lines
                    sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{
                        console.log('stop', response);
                    });
                }
            }
        });
    };

    const mainWrapper = document.querySelector('.v-main__wrap');
    // Create an observer instance linked to the callback function
    const wrapperObserver = new MutationObserver(mainWrapperCallback);

    // Start observing the target node for configured mutations
    wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true });
})();
Thx a lot! Are you able to edit it?
You are welcome, I'm not sure what do you want to edit on this, but anyone could do it.
But I can change things, if you have recommendations.
Would be great to shorten the tease. Every image is too long / there is a lack of input. It's just like fapping 30 seconds for a single sentence. And the first "hour" in a slow rhythm. A 10 Minute "impossible POT-Challenge" is good enough, where you have to have your orgasm at least at minute 7 or 8.
Ghingis
Explorer At Heart
Explorer At Heart
Posts: 177
Joined: Mon Oct 24, 2011 4:55 pm

Re: [RELEASE] Impossible POT Challenge

Post by Ghingis »

Achatius wrote: Sat Jan 08, 2022 8:30 am Would be great to shorten the tease. Every image is too long / there is a lack of input. It's just like fapping 30 seconds for a single sentence. And the first "hour" in a slow rhythm. A 10 Minute "impossible POT-Challenge" is good enough, where you have to have your orgasm at least at minute 7 or 8.
You really missed something, I'm not the one who made the tease. I just made a script, that controls your handy to the speed of the beat.. So no I can not shorten the tease.
Post Reply