diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7745062 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* -text diff --git a/.github/workflows/deploy-to-gh-pages.yml b/.github/workflows/deploy-to-gh-pages.yml new file mode 100644 index 0000000..1fab66e --- /dev/null +++ b/.github/workflows/deploy-to-gh-pages.yml @@ -0,0 +1,23 @@ +name: build demo + +on: + workflow_dispatch: + push: + pull_request: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + + - uses: hyoo-ru/mam_build@master2 + with: + package: optimade/tmdne + modules: app + + - uses: JamesIves/github-pages-deploy-action@4.1.7 + with: + branch: gh-pages + folder: optimade/tmdne/app/- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3e8fe6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +-* diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 16a0d37..0000000 --- a/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -from python:3.11-slim-buster - -copy . /app -workdir /app -run pip install -r requirements.txt -cmd gunicorn src.this_material_does_not_exist.app:server -b 0.0.0.0:8050 diff --git a/LICENSE b/LICENSE index c7c2544..0d0e9f4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2023 Matthew Evans - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2023 Matthew Evans + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index a81ec6f..65e29ef 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,38 @@ -

💎 this-material-does-not-exist 💎

+

💎 this-material-does-not-exist 💎

Get given random crystal structures predicted by ML materials discovery projects, and vote on whether you think it should be synthesizable (or, at least, whether it is worth trying!) -Currently uses [crystaltoolkit](https://docs.crystaltoolkit.org) and data from the +Currently uses [cifplayer](https://github.com/tilde-lab/cifplayer) and data from the [OPTIMADE API](https://optimade.org) for the recent [Google DeepMind paper](https://github.com/google-deepmind/materials_discovery). +The physical properties prediction is done dynamically by [MPDS ML server](https://mpds.io/ml). -![2023-12-10-001838_1095x878_scrot](https://github.com/ml-evs/this-material-does-not-exist/assets/7916000/678ba7ec-d929-438e-8637-3dad5bf26493) +![GNome_d582d1239f_screenshot](https://raw.githubusercontent.com/mpds-io/this-material-does-not-exist/main/d582d1239f.png) + + +## Build + +The `cifplayer` is powered by `$mol` framework. Note that, unlike many other frontend frameworks, `$mol` provides the same single environment for all its projects, under the standard namespace scheme. That is, all your `$mol`-based code lives inside the same directory `$MOL_HOME`. So if you don't have `$MOL_HOME` yet, please create it and navigate there + +```bash +mkdir $MOL_HOME && cd $MOL_HOME +``` + +Then build with + +```bash +npm exec mam optimade/tmdne/app +``` + +This will fetch the MAM server (MAM stands for the `$mol` abstract modules), clone this project, and compile it inside `optimade/tmdne/app/-/` subfolder. You will need the `web.js` bundle, that's it. + + +## Develop + +Similarly to above, inside the `$MOL_HOME`, start the MAM dev-server with + +```bash +npm exec mam +``` + +and navigate to http://localhost:9080, there select `optimade` namespace, then `tmdne`, then `app`. As you go through the folder structure, the selected project is being cloned and compiled on the fly, inside the corresponding subfolder of `$MOL_HOME`. diff --git a/app/app.view.css b/app/app.view.css new file mode 100644 index 0000000..6a11ea7 --- /dev/null +++ b/app/app.view.css @@ -0,0 +1,8 @@ +@media all and (max-width: 850px) { + [optimade_tmdne_app_param_mae], [optimade_tmdne_app_param_name] { display: none; } + [optimade_tmdne_app_acks] { display: none; } +} + +@media all and (max-height: 650px) { + [optimade_tmdne_app_prediction] { display: none; } +} diff --git a/app/app.view.css.ts b/app/app.view.css.ts new file mode 100644 index 0000000..31010bc --- /dev/null +++ b/app/app.view.css.ts @@ -0,0 +1,151 @@ +namespace $.$$ { + + $mol_style_define( $optimade_tmdne_app, { + + overflow: 'hidden', + flex: { + direction: 'column', + }, + align: { + items: 'center', + }, + + Player: { + flex: { + grow: 1, + }, + width: '100%', + opacity: 1, + transition: 'opacity 0.15s', + '[optimade_tmdne_app_player_hidden]': { + 'true': { + opacity: 0.1, + }, + }, + }, + + Head_space: { + position: 'absolute', + top: $mol_gap.block, + left: 0, + right: 0, + flex: { + grow: 1, + }, + pointerEvents: 'none', + }, + + Head_card: { + pointerEvents: 'auto', + margin: 'auto', + width: '35%', + textAlign: 'center', + }, + + Head_title: { + userSelect: 'none', + justify: { + content: 'center', + }, + font: { + size: '1.2rem', + }, + }, + + Prediction: { + userSelect: 'none', + font: { + size: '0.7rem', + }, + lineHeight: '16px', + flex: { + grow: 0, + wrap: 'wrap', + }, + position: 'absolute', + left: $mol_gap.block, + bottom: '11rem', + pointerEvents: 'none', + opacity: 1, + transition: 'opacity 0.15s', + '[optimade_tmdne_app_prediction_hidden]': { + 'true': { + opacity: 0, + }, + }, + }, + + Param: { + gap: '0.3rem', + flex: { + wrap: 'wrap', + }, + }, + + Param_name: { + font: { + weight: 700, + }, + }, + + Param_symbol: { + flex: { + direction: 'row', + }, + }, + + Param_unit: { + flex: { + direction: 'row', + }, + }, + + Param_mae_unit: { + flex: { + direction: 'row', + }, + }, + + Param_value: { + gap: '0.25rem', + }, + + Foot: { + justify: { + content: 'space-between', + }, + width: '24rem', + position: 'absolute', + bottom: '5.3rem', + + pointerEvents: 'none', + transition: 'opacity 0.2s', + opacity: 1, + '[optimade_tmdne_app_foot_hidden]': { + 'true': { + opacity: 0, + }, + }, + zIndex: 1, + }, + + Hint_no: { + pointerEvents: 'auto', + color: '#ff6666', + }, + + Hint_yes: { + pointerEvents: 'auto', + color: $mol_theme.current, + }, + + Acks: { + font: { + size: '0.7rem', + }, + zIndex: 0, + }, + + } ) + +} diff --git a/app/app.view.tree b/app/app.view.tree new file mode 100644 index 0000000..da5a6de --- /dev/null +++ b/app/app.view.tree @@ -0,0 +1,92 @@ +$optimade_tmdne_app $mol_view + title \This Material Does Not Exist? + number? 1 + plugins / + <= Theme $mol_theme_auto + rotating? false + number_swiped? 0 + number_prefetch? 0 + sub / + <= Player $optimade_cifplayer_player + fullscreen? => player_fullscreen? + attr * + fullscreen <= player_fullscreen? + optimade_tmdne_app_player_hidden <= card_holding + data <= json null + Fullscreen null + Overlays null + event * + pointerdown? <=> player_pointerdown? null + pointerup? <=> player_pointerup? null + <= Head_space $mol_view + sub / + <= Head_card $mol_list + sub / + <= Head_title $mol_paragraph + title \Does this material exist? + <= Prediction $mol_list + attr * + optimade_tmdne_app_prediction_hidden <= rotating + sub <= params / + <= Param* $mol_view + sub / + <= Param_name* $mol_paragraph + title <= param_name* \ + <= Param_symbol* $mol_html_view + minimal_height <= param_min_height 22 + html <= param_symbol* \ + \= + <= Param_value* $mol_view + sub / + <= param_value* \ + <= Param_unit* $mol_html_view + minimal_height <= param_min_height + html <= param_unit* \ + <= Param_mae* $mol_view + sub / + \(± + <= param_mae* \ + <= Param_mae_unit* $mol_html_view + minimal_height <= param_min_height + html <= param_unit* \ + \) + <= Foot $mol_view + attr * + optimade_tmdne_app_foot_hidden <= rotating + sub / + <= Hint_no $mol_button_minor + title \ᐊ No + click? <=> click_no? null + <= Hint_yes $mol_button_minor + title \Yes ᐅ + click? <=> click_yes? null + ^ cards / <= Card* $optimade_tmdne_card + name <= card_name* \ + loaded <= card_loaded* false + why? <=> why*? \ + pointer_holding? <=> card_holding? false + swiped_to? <=> swiped_to*? \ + swipe_to_right => swipe_to_right* + swipe_to_left => swipe_to_left* + <= Acks $mol_view + sub / + <= Acks_a $mol_link + uri \https://www.optimade.org + sub / + \Powered by Optimade + <= Acks_b $mol_link + uri \https://github.com/tilde-lab/cifplayer + sub / + \and cifplayer + <= Acks_c $mol_link + uri \https://github.com/google-deepmind/materials_discovery + sub / + \using the GNome dataset + <= Acks_d $mol_link + uri \https://github.com/ml-evs/this-material-does-not-exist + sub / + \developed on GitHub + <= Acks_e $mol_link + uri \https://thispersondoesnotexist.com + sub / + \and inspired by... diff --git a/app/app.view.ts b/app/app.view.ts new file mode 100644 index 0000000..425935f --- /dev/null +++ b/app/app.view.ts @@ -0,0 +1,191 @@ +namespace $.$$ { + + export class $optimade_tmdne_app extends $.$optimade_tmdne_app { + + @ $mol_mem_key + fetch_by_number( number: number ) { + $mol_wire_solid() + return this.$.$mol_fetch.json( `https://optimade-gnome.odbx.science/v1/structures?page_limit=1&page_offset=${number}` ) as any + } + + @ $mol_mem_key + predict_by_number( number: number ) { + $mol_wire_solid() + + const structure = JSON.stringify( this.fetch_by_number( number ) ) + const params = new URLSearchParams({ structure }) + const url = `https://labs.mpds.io/predict` + + const prediction = this.$.$mol_wire_sync( this ).$.$mol_fetch.success( url, { + method: 'post', + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: params.toString(), + } ).json() ?? {} as any + + return prediction + } + + @ $mol_mem + json() { + return this.fetch_by_number( this.number() ) + } + + @ $mol_mem_key + card_name( n: number ) { + const json = this.fetch_by_number( n ) + let str = json?.data[ 0 ]?.attributes?.chemical_formula_reduced + return formula_html( str ) + } + + @ $mol_mem_key + card_loaded( n: number ) { + try { + this.card_name( n ) + return this.number() === n + } catch (error) { + if( $mol_promise_like( error ) ) return false + } + return false + } + + cards(): readonly ( any )[] { + const swiped = this.number_swiped() + return [ + this.Card( this.number_prefetch() ), + ... swiped ? [ this.Card( swiped ) ] : [], + this.Card( this.number() ), + ] + } + + @ $mol_action + random_sample() { + return random_int( 1, 384937 ) + } + + @ $mol_mem + number( next?: number ): number { + return next ?? this.random_sample() + } + + @ $mol_mem + number_prefetch( next?: number ): number { + return next ?? this.random_sample() + } + + @ $mol_action + update() { + this.number_swiped( this.number() ) + this.number( this.number_prefetch() ) + const prefetch = this.random_sample() + this.number_prefetch( prefetch ) + $mol_wire_async( this ).predict_by_number( prefetch ) + } + + @ $mol_mem + predict() { + return this.predict_by_number( this.number() ) + } + + @ $mol_mem + params(): readonly any[] { + const keys = Object.keys( this.predict().prediction ) + return keys.map( k => this.Param( k ) ) + } + + @ $mol_mem_key + param_value( id: any ): string { + return this.predict().prediction[id].value ?? '' + } + + @ $mol_mem_key + param_mae( id: any ): string { + return this.predict().prediction[id].mae ?? '' + } + + @ $mol_mem_key + param_name( id: any ): string { + return this.predict().legend[id].name ?? '' + } + + @ $mol_mem_key + param_unit( id: any ): string { + return this.predict().legend[id].gui_units ?? '' + } + + @ $mol_mem_key + param_symbol( id: any ): string { + return this.predict().legend[id].symbol ?? '' + } + + player_pointerdown( next?: any ) { + this.rotating( true ) + } + + player_pointerup( next?: any ) { + this.rotating( false ) + } + + click_no() { + this.swipe_to_left( this.number() ) + } + + click_yes() { + this.swipe_to_right( this.number() ) + } + + @ $mol_mem_key + swiped_to( id: number, next?: string ) { + + const vote = next == 'left' ? 0 : next == 'right' ? 1 : undefined + if( vote !== undefined ) { + + this.update() + const params = new URLSearchParams( { + id: this.fetch_by_number( id )?.data[ 0 ]?.attributes?._gnome_material_id, + comment: this.why( id ), + vote: vote.toString(), + } ) + + this.$.$mol_fetch.success( 'https://crus.absolidix.com', { + method: 'post', + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: params.toString(), + } ) + + } + + return next ?? '' + } + + } + + function random_int( min: number, max: number ) { + return Math.floor( Math.random() * ( max - min + 1 ) ) + min + } + + function formula_html( str: string ) { + let sub = false + let html = '' + for( let i = 0; i < str.length; i++ ) { + if( !isNaN( +str[ i ] ) || str[ i ] == '.' ) { + if( !sub ) { + html += '' + sub = true + } + } else { + if( sub ) { + html += '' + sub = false + } + } + html += str[ i ] + } + if( sub ) html += '' + return html ?? '' + } + +} diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..efcd8ed --- /dev/null +++ b/app/index.html @@ -0,0 +1,13 @@ + + + + + + + + + +
+ + + diff --git a/card/card.view.css.ts b/card/card.view.css.ts new file mode 100644 index 0000000..0fb9d55 --- /dev/null +++ b/card/card.view.css.ts @@ -0,0 +1,113 @@ +namespace $.$$ { + + $mol_style_define( $optimade_tmdne_card, { + + pointerEvents: 'auto', + width: 'max-content', + position: 'fixed', + left: '50%', + transform: 'translateX(-50%)', + bottom: '1.6rem', + zIndex: 2, + + // position: 'relative', + // left: 0, + // right: 0, + // width: '100%', + // margin: 'auto', + // overflow: 'hidden', + // flex: { + // grow: 1, + // }, + + padding: '0.5rem', + Float: { + margin: 'auto', + }, + + Card_float: { + background: { + color: $mol_theme.back, + }, + transform: 'translateY(125%)', + transition: 'transform 0.7s', + '[loaded]': { + 'true': { + transform: 'none', + }, + }, + border: { + radius: $mol_gap.round, + }, + boxShadow: '0 0 0.5rem 0rem hsla(0,0%,0%,.125)', + }, + + Card_content: { + flex: { + direction: 'column', + }, + background: { + color: $mol_style_func.hsla( 210, 80, 50, 0.3 ), + }, + padding: $mol_gap.block, + border: { + radius: $mol_gap.round, + }, + '[card_position]': { + 'right': { + background: { + color: $mol_style_func.hsla( 120, 80, 50, 0.3 ), + }, + }, + 'left': { + background: { + color: $mol_style_func.hsla( 0, 80, 50, 0.3 ), + }, + }, + }, + }, + + Name: { + flex: { + direction: 'row', + }, + padding: { + bottom: '0.5rem', + }, + justify: { + content: 'center', + }, + font: { + weight: 700, + size: '1.5rem', + }, + }, + + Question: { + justify: { + content: 'center', + }, + padding: { + bottom: '0.5rem', + }, + }, + + Why: { + pointerEvents: 'auto', + maxWidth: '20rem', + }, + + Why_label: { + gap: '0.5rem', + }, + + Why_optional: { + color: $mol_theme.shade, + font: { + style: 'italic', + }, + }, + + } ) + +} diff --git a/card/card.view.tree b/card/card.view.tree new file mode 100644 index 0000000..fecfe84 --- /dev/null +++ b/card/card.view.tree @@ -0,0 +1,23 @@ +$optimade_tmdne_card $optimade_tmdne_swipe + allowed <= loaded false + content / + <= Card_float $mol_view + attr * + loaded <= loaded + sub / <= Card_content $mol_view + attr * + card_position <= card_position \ + sub / + <= Name $mol_html_view + minimal_height 22 + html <= name \ + <= Question $mol_paragraph + title \Do you think it's synthesizable? + <= Why_label $mol_view + sub / + <= Why_title $mol_paragraph + title \Why? + <= Why_optional $mol_paragraph + title \(optional) + <= Why $mol_textarea + value? <=> why? \ diff --git a/card/card.view.ts b/card/card.view.ts new file mode 100644 index 0000000..205ee00 --- /dev/null +++ b/card/card.view.ts @@ -0,0 +1,12 @@ +namespace $.$$ { + + export class $optimade_tmdne_card extends $.$optimade_tmdne_card { + + @ $mol_mem + card_position(): string { + return this.swiped_to() || this.passed() || '' + } + + } + +} diff --git a/d582d1239f.png b/d582d1239f.png new file mode 100644 index 0000000..8aab0ed Binary files /dev/null and b/d582d1239f.png differ diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 5cf4480..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -httpx -crystal-toolkit -optimade[pymatgen] -gunicorn diff --git a/results.csv b/results.csv deleted file mode 100644 index 5f03388..0000000 --- a/results.csv +++ /dev/null @@ -1,261 +0,0 @@ -813805a1-179a-442b-b9da-1555b816138f,a8ba8cc16a,1 -813805a1-179a-442b-b9da-1555b816138f,4c4300b256,2 -813805a1-179a-442b-b9da-1555b816138f,4c4300b256,3 -813805a1-179a-442b-b9da-1555b816138f,4c4300b256,4 -813805a1-179a-442b-b9da-1555b816138f,4c4300b256,5 -813805a1-179a-442b-b9da-1555b816138f,48c04ddda9,1 -052430ea-71a4-45e0-a41c-6ff306996832,08f12dbe96,1 -052430ea-71a4-45e0-a41c-6ff306996832,373e1dabfe,2 -052430ea-71a4-45e0-a41c-6ff306996832,0ed077f153,2 -052430ea-71a4-45e0-a41c-6ff306996832,c3c11010ac,3 -052430ea-71a4-45e0-a41c-6ff306996832,ae4cf9267c,1 -052430ea-71a4-45e0-a41c-6ff306996832,8bf08247fa,1 -052430ea-71a4-45e0-a41c-6ff306996832,ae25695182,2 -052430ea-71a4-45e0-a41c-6ff306996832,feee8c9d63,3 -052430ea-71a4-45e0-a41c-6ff306996832,42769a42a5,1 -052430ea-71a4-45e0-a41c-6ff306996832,9fb7d29912,1 -052430ea-71a4-45e0-a41c-6ff306996832,9cd7028825,1 -052430ea-71a4-45e0-a41c-6ff306996832,f93489bf43,1 -052430ea-71a4-45e0-a41c-6ff306996832,ace503fa98,1 -052430ea-71a4-45e0-a41c-6ff306996832,85eed2ff79,2 -052430ea-71a4-45e0-a41c-6ff306996832,ef3ec0fe29,1 -052430ea-71a4-45e0-a41c-6ff306996832,46111b4fd6,1 -052430ea-71a4-45e0-a41c-6ff306996832,1355778f40,2 -052430ea-71a4-45e0-a41c-6ff306996832,fd48845ad0,3 -2023-12-10T01:35:29.183831,335e4fb7-ebfb-40be-a67b-c9b5986861f3,08f12dbe96,1 -2023-12-10T01:36:05.953010,335e4fb7-ebfb-40be-a67b-c9b5986861f3,373e1dabfe,2 -2023-12-10T01:36:15.569456,335e4fb7-ebfb-40be-a67b-c9b5986861f3,29996413f6,3 -2023-12-10T01:37:03.436101,335e4fb7-ebfb-40be-a67b-c9b5986861f3,b7866d38a4,1 -2023-12-10T01:40:07.901205,335e4fb7-ebfb-40be-a67b-c9b5986861f3,ae4cf9267c,2 -2023-12-10T01:53:25.229727,172.31.48.11,08f12dbe96,1 -2023-12-10T01:53:37.527790,172.31.48.11,373e1dabfe,2 -2023-12-10T04:39:08.401134,172.31.48.11,2032820f51,1 -2023-12-10T07:52:41.831894,172.31.48.11,2871f6d074,1 -2023-12-10T07:52:49.369994,172.31.48.11,8bf08247fa,2 -2023-12-10T07:52:58.968660,172.31.48.11,61f0bde892,3 -2023-12-10T08:40:09.841372,172.31.48.11,fe77f9ad05,1 -2023-12-10T08:40:40.469997,172.31.48.11,474990c5d5,2 -2023-12-10T08:41:56.930155,172.31.48.11,cd58cf65f4,1 -2023-12-10T08:42:11.230770,172.31.48.11,02fb284d16,2 -2023-12-10T08:42:13.081288,172.31.48.11,184bdb616c,3 -2023-12-10T08:42:27.729663,172.31.48.11,42769a42a5,4 -2023-12-10T08:44:22.294723,172.31.48.11,0a627e5e0c,5 -2023-12-10T08:44:29.163058,172.31.48.11,9fb7d29912,6 -2023-12-10T08:44:32.369661,172.31.48.11,9cd7028825,7 -2023-12-10T08:44:40.858716,172.31.48.11,74175f9642,1 -2023-12-10T08:44:42.146964,172.31.48.11,b1e7320905,8 -2023-12-10T08:44:47.722387,172.31.48.11,e34e18dd40,9 -2023-12-10T08:44:52.606806,172.31.48.11,d90550ac56,10 -2023-12-10T08:45:01.197856,172.31.48.11,5088f350e8,11 -2023-12-10T08:45:26.772820,172.31.48.11,22e3d0722b,12 -2023-12-10T09:04:49.820630,172.31.48.11,b5aa020a86,1 -2023-12-10T09:28:48.400872,172.31.48.11,38b594b9f0,1 -2023-12-10T09:28:57.459704,172.31.48.11,6b98dbca69,2 -2023-12-10T09:29:09.253819,172.31.48.11,5d89fc9011,3 -2023-12-10T10:12:28.754033,172.31.48.11,85eed2ff79,1 -2023-12-10T10:12:43.296791,172.31.48.11,3068b9a4b4,2 -2023-12-10T10:13:16.239041,172.31.48.11,ef3ec0fe29,3 -2023-12-10T10:47:21.519517,172.31.48.11,4810103dc8,1 -2023-12-10T11:42:18.309595,172.31.48.11,2d984e0731,1 -2023-12-10T11:42:23.584336,172.31.48.11,396a22636d,2 -2023-12-10T11:42:30.598941,172.31.48.11,aa68bc5ea6,3 -2023-12-10T11:42:32.480918,172.31.48.11,1e42be3bf6,4 -2023-12-10T11:42:33.469528,172.31.48.11,b9c0483275,5 -2023-12-10T11:42:34.091270,172.31.48.11,9342aaea05,6 -2023-12-10T11:42:35.224948,172.31.48.11,da3368a66d,7 -2023-12-10T11:42:36.071050,172.31.48.11,f814051baf,8 -2023-12-10T11:42:36.670731,172.31.48.11,2a3bd925a4,9 -2023-12-10T11:42:37.832525,172.31.48.11,b443ba681d,10 -2023-12-10T11:42:38.947643,172.31.48.11,b178b4b60b,11 -2023-12-10T11:42:39.713972,172.31.48.11,5d89fc9011,12 -2023-12-10T11:42:40.713326,172.31.48.11,f8410244a9,13 -2023-12-10T11:42:41.882827,172.31.48.11,c3c11010ac,14 -2023-12-10T11:42:42.867798,172.31.48.11,d9305374dd,15 -2023-12-10T11:42:44.038933,172.31.48.11,18617e1fb5,16 -2023-12-10T11:42:45.052252,172.31.48.11,bd4841bdf2,17 -2023-12-10T11:42:45.931141,172.31.48.11,ddc2576fb5,18 -2023-12-10T11:42:46.963853,172.31.48.11,77fca3844d,19 -2023-12-10T11:42:47.927634,172.31.48.11,56b1701b36,20 -2023-12-10T11:42:48.728264,172.31.48.11,c6e96e8418,21 -2023-12-10T11:42:49.786490,172.31.48.11,16d7a580f0,22 -2023-12-10T12:30:59.366286,172.31.48.11,1f46285073,1 -2023-12-10T12:33:31.625799,172.31.48.11,5a907bd5fc,2 -2023-12-10T14:46:09.137306,172.31.48.11,5a7f6fa180,1 -2023-12-10T14:46:33.444553,172.31.48.11,0ddc2ad967,2 -2023-12-10T15:30:45.443668,172.31.48.11,e1a304f4f9,1 -2023-12-10T15:52:51.706618,172.31.48.11,52c7b79e28,1 -2023-12-10T15:53:00.560805,172.31.48.11,5585fa5df2,2 -2023-12-10T15:53:04.628762,172.31.48.11,06aa9aba77,3 -2023-12-10T16:54:12.697351,172.31.48.11,67f06bea1b,3 -2023-12-10T18:43:48.233081,172.31.48.11,d481302ccb,1 -2023-12-10T18:44:18.340928,172.31.48.11,81aca8f34b,2 -2023-12-10T18:44:30.769207,172.31.48.11,b84a10bc99,3 -2023-12-10T19:28:43.219652,172.31.48.11,5a233705a7,1 -2023-12-10T19:41:38.989798,172.31.48.11,f94ce15e95,1 -2023-12-10T19:42:54.225213,172.31.48.11,a397e8a674,2 -2023-12-10T21:14:49.053379,172.31.48.11,0833d2b586,2 -2023-12-10T21:14:50.380240,172.31.48.11,609b04ad0a,3 -2023-12-10T21:14:50.626487,172.31.48.11,609b04ad0a,4 -2023-12-10T21:14:50.909309,172.31.48.11,609b04ad0a,5 -2023-12-10T21:14:57.828872,172.31.48.11,77fe38ef14,6 -2023-12-10T21:15:05.176034,172.31.48.11,7637c6768e,7 -2023-12-10T21:45:02.395845,172.31.48.11,ca0509de66,1 -2023-12-10T21:45:20.499606,172.31.48.11,089845da40,2 -2023-12-10T21:45:31.744310,172.31.48.11,e32a217602,3 -2023-12-10T21:45:38.619462,172.31.48.11,f1114bb798,4 -2023-12-10T21:46:10.468585,172.31.48.11,e5d42e2749,5 -2023-12-10T21:46:22.314337,172.31.48.11,d583bca697,6 -2023-12-10T21:46:34.861474,172.31.48.11,5915704b68,7 -2023-12-10T21:46:37.861299,172.31.48.11,4d84e5d5b1,8 -2023-12-10T21:49:27.160548,172.31.48.11,fbca34bf6a,9 -2023-12-10T21:49:35.469406,172.31.48.11,a8e20d3180,10 -2023-12-10T21:49:50.927423,172.31.48.11,ca39d06493,11 -2023-12-10T21:50:08.705153,172.31.48.11,cce2560603,12 -2023-12-10T21:50:18.603789,172.31.48.11,060e7101a6,13 -2023-12-10T21:50:22.818791,172.31.48.11,f7479791f4,14 -2023-12-10T21:50:28.741450,172.31.48.11,5d8f30a894,15 -2023-12-10T21:50:39.680865,172.31.48.11,3c61ed4d8d,16 -2023-12-10T21:50:41.796087,172.31.48.11,904280c87b,17 -2023-12-10T21:50:46.225198,172.31.48.11,87f1f3d8eb,18 -2023-12-10T21:55:34.162429,172.31.48.11,b92e677f98,19 -2023-12-10T21:56:05.493748,172.31.48.11,2d156a895c,20 -2023-12-10T21:56:08.948198,172.31.48.11,bd4841bdf2,21 -2023-12-10T21:56:12.408506,172.31.48.11,7484354c22,22 -2023-12-10T21:56:14.455737,172.31.48.11,8a825332e9,23 -2023-12-10T21:56:31.478971,172.31.48.11,beb8b638a3,24 -2023-12-10T21:56:42.929347,172.31.48.11,e7c9c3fd05,25 -2023-12-10T21:57:17.158976,172.31.48.11,5248a8de80,26 -2023-12-10T21:59:00.815424,172.31.48.11,f15f043fe7,27 -2023-12-10T21:59:15.734561,172.31.48.11,b0e03c8a4b,28,30 -2023-12-10T22:22:51.881985,172.31.48.11,29996413f6,1,20 -2023-12-10T22:23:03.372048,172.31.48.11,c3c11010ac,2,50 -2023-12-10T23:20:02.673454,172.31.48.11,4d99b1d990,1,50 -2023-12-10T23:20:14.229172,172.31.48.11,a51f0a97c0,2,100 -2023-12-10T23:20:21.139649,172.31.48.11,33e42a3c1a,3,50 -2023-12-10T23:20:38.142765,172.31.48.11,2032820f51,4,0 -2023-12-10T23:20:46.541335,172.31.48.11,6ea3e53db0,5,100 -2023-12-10T23:20:53.534309,172.31.48.11,2454bfcde1,6,0 -2023-12-11T07:24:29.099660,172.31.48.11,fb7e18c3b5,1,30 -2023-12-11T07:24:37.651226,172.31.48.11,26b5e16af3,2,30 -2023-12-11T13:39:58.513373,172.31.48.11,27e8fe6fe7,1,70 -2023-12-12T11:05:11.032420,172.31.48.11,184bdb616c,1,0 -2023-12-12T12:24:19.083940,172.31.48.11,9fb7d29912,1,0 -2023-12-12T12:45:32.855150,172.31.48.11,e34e18dd40,1,10 -2023-12-12T12:45:52.148692,172.31.48.11,5088f350e8,2,10 -2023-12-12T12:47:05.045739,172.31.48.11,22e3d0722b,3,10 -2023-12-12T12:48:50.641761,172.31.48.11,29996413f6,4,20 -2023-12-12T12:51:11.514975,172.31.48.11,b5aa020a86,5,10 -2023-12-12T12:51:48.741610,172.31.48.11,3c61ed4d8d,6,10 -2023-12-12T12:53:51.468949,172.31.48.11,b830de4210,7,10 -2023-12-12T12:54:03.380300,172.31.48.11,7274606d10,8,10 -2023-12-12T12:54:37.455742,172.31.48.11,f93489bf43,9,10 -2023-12-12T12:57:02.531810,172.31.48.11,38b594b9f0,10,30 -2023-12-12T12:57:13.080252,172.31.48.11,6b98dbca69,11,50 -2023-12-12T12:57:22.199671,172.31.48.11,5d89fc9011,12,10 -2023-12-12T12:59:05.116814,172.31.48.11,ace503fa98,13,10 -2023-12-12T12:59:34.917430,172.31.48.11,85eed2ff79,14,50 -2023-12-12T13:29:52.021308,172.31.48.11,ef3ec0fe29,1,80 -2023-12-12T13:30:24.010926,172.31.48.11,233b8a3c43,2,20 -2023-12-12T16:42:57.972303,172.31.48.11,9cbe35530e,1,0 -2023-12-12T16:42:59.052957,172.31.48.11,ee248120d7,2,0 -2023-12-12T16:48:02.699372,172.31.48.11,c9e4ebe1af,1,0 -2023-12-12T16:48:15.246189,172.31.48.11,6ea56365f1,2,0 -2023-12-13T02:03:10.100772,172.31.48.11,2d984e0731,1,70 -2023-12-13T11:47:57.296647,172.31.48.11,1e42be3bf6,1,70 -2023-12-13T13:43:09.442535,172.31.48.11,f814051baf,1,10 -2023-12-13T13:43:10.048567,172.31.48.11,2a3bd925a4,2,10 -2023-12-13T13:43:58.978255,172.31.48.11,b443ba681d,3,10 -2023-12-13T20:59:45.588906,172.31.48.11,08f12dbe96,50,1,'too much silicon' -2023-12-28T08:03:16.472476,172.31.48.11,ae25695182,70,1,'' -2024-01-16T20:55:31.063683,172.31.48.5,3c61ed4d8d,50,1,'Na2LiYCl6' -2024-01-16T20:56:24.728380,172.31.48.5,b830de4210,50,2,'' -2024-01-16T20:56:25.865390,172.31.48.5,bbafca2c58,50,3,'' -2024-01-16T20:56:27.074549,172.31.48.5,7274606d10,50,4,'' -2024-01-16T20:56:39.814852,172.31.48.5,f93489bf43,100,5,'' -2024-01-16T20:56:51.033777,172.31.48.5,38b594b9f0,100,6,'' -2024-01-16T20:56:54.827206,172.31.48.5,6b98dbca69,50,7,'' -2024-01-18T18:26:14.920275,172.31.48.5,233b8a3c43,100,1,'' -2024-01-18T18:26:16.917842,172.31.48.5,46111b4fd6,100,2,'' -2024-01-18T18:26:23.741739,172.31.48.5,2d302172db,100,3,'' -2024-01-19T16:17:34.590555,172.31.48.5,ee248120d7,100,1,'' -2024-01-19T16:17:56.594553,172.31.48.5,4810103dc8,50,2,'' -2024-01-19T16:18:09.267377,172.31.48.5,c9e4ebe1af,50,3,'' -2024-01-19T16:18:15.405813,172.31.48.5,6ea56365f1,50,4,'' -2024-01-19T16:18:23.752652,172.31.48.5,f4fe02cdf6,50,5,'' -2024-01-19T16:18:28.364266,172.31.48.5,15d1c55782,50,6,'' -2024-01-19T16:18:58.815686,172.31.48.5,96ec757620,50,7,'' -2024-01-19T16:19:04.905643,172.31.48.5,394472c73e,50,8,'' -2024-01-19T16:19:11.956784,172.31.48.5,2d984e0731,50,9,'' -2024-01-19T16:19:28.358419,172.31.48.5,396a22636d,50,10,'' -2024-01-19T16:19:31.637337,172.31.48.5,aa68bc5ea6,50,11,'' -2024-01-19T16:19:47.575308,172.31.48.5,1e42be3bf6,50,12,'' -2024-02-14T16:14:19.363408,172.31.48.12,67f06bea1b,20,1,'' -2024-02-24T12:18:39.897846,172.31.48.12,83db638923,20,1,'' -2024-03-03T02:43:37.852303,172.31.48.12,f93489bf43,90,1,'' -2024-03-03T02:45:34.056045,172.31.48.12,fd48845ad0,70,1,'' -2024-03-05T08:04:31.024660,172.31.48.12,2a3bd925a4,0,1,'' -2024-03-07T00:03:07.176115,172.31.48.12,5d89fc9011,0,1,'' -2024-03-07T00:03:12.681870,172.31.48.12,f8410244a9,0,2,'' -2024-03-07T00:03:16.087938,172.31.48.12,c3c11010ac,0,3,'' -2024-03-07T00:03:22.378839,172.31.48.12,d9305374dd,0,4,'' -2024-03-07T00:03:26.573822,172.31.48.12,18617e1fb5,0,5,'' -2024-03-07T00:03:35.790353,172.31.48.12,bd4841bdf2,0,6,'' -2024-03-07T00:03:56.033913,172.31.48.12,ddc2576fb5,0,7,'' -2024-03-24T23:24:33.769734,172.31.48.21,6ea3e53db0,30,1,'' -2024-03-25T19:18:02.604763,172.31.48.21,b1fd30944c,0,1,'' -2024-03-25T19:18:17.538123,172.31.48.21,b34312e784,0,2,'' -2024-03-25T19:19:10.513764,172.31.48.21,783030bd26,0,3,'' -2024-03-25T19:19:27.330949,172.31.48.21,672205188c,0,4,'' -2024-03-25T19:19:40.120784,172.31.48.21,e34e18dd40,0,5,'' -2024-03-25T19:49:18.373076,172.31.48.21,b715a6eeab,20,1,'it can be difficult to find someone who wants to deal with radioactive Tc' -2024-03-25T19:51:28.318843,172.31.48.21,f7f1897372,10,2,'Protactinium (Pa) is one of the rarest and most expensive naturally occurring elements. (from Wikipedia)' -2024-03-25T20:01:29.258004,172.31.48.21,184bdb616c,70,1,'' -2024-03-25T20:02:34.229114,172.31.48.21,02fb284d16,10,1,'it is unlikely that Tb, Pr and Lu would order as predicted here. the material might exist in a higher symmetry space group with Tb,Pr and Lu disordered, then it should be written as (Tb,Pr,Lu)5Sn4' -2024-03-25T20:09:58.519545,172.31.48.21,fd48845ad0,0,1,'loose MgBr molecules in a crystals are not a thing' -2024-03-25T20:10:04.188062,172.31.48.21,07570a66bc,0,2,'' -2024-03-25T20:10:45.706989,172.31.48.21,9cbe35530e,0,3,'noooooo' -2024-03-25T20:48:01.556761,172.31.48.21,1e42be3bf6,60,1,'' -2024-03-25T20:48:02.267954,172.31.48.21,1e42be3bf6,60,2,'' -2024-03-25T20:48:11.353763,172.31.48.21,f814051baf,30,3,'' -2024-03-25T20:48:18.438292,172.31.48.21,2a3bd925a4,30,4,'' -2024-03-25T20:59:36.144502,172.31.48.21,d9305374dd,10,2,'Pr and Tb are likely to be disordered, strange coordinations' -2024-03-25T20:59:46.745741,172.31.48.21,d9305374dd,10,1,'Pr and Tb are likely to be disordered, strange coordinations' -2024-03-25T22:33:17.898483,172.31.48.21,e8ccd3fc77,50,1,'' -2024-03-25T22:33:23.167990,172.31.48.21,a6dc87910a,50,2,'' -2024-03-25T22:33:29.377579,172.31.48.21,d31da9d6dc,50,3,'' -2024-03-25T22:35:12.090498,172.31.48.21,62f68203f1,50,1,'' -2024-03-25T22:35:13.974530,172.31.48.21,280b630a85,50,2,'' -2024-03-25T22:50:38.024442,172.31.48.21,13ff474841,80,1,'' -2024-03-25T22:50:45.435729,172.31.48.21,d04b7c0a0c,20,2,'' -2024-03-26T07:02:18.517726,172.31.48.21,83bf568487,90,1,'' -2024-03-26T07:02:28.421269,172.31.48.21,d481302ccb,90,2,'' -2024-03-26T07:11:52.783329,172.31.48.21,5a907bd5fc,20,1,'' -2024-03-26T07:25:02.854034,172.31.48.21,b84a10bc99,10,2,'' -2024-03-26T07:25:17.928210,172.31.48.21,089845da40,40,3,'' -2024-03-26T07:25:44.998067,172.31.48.21,c4adb64fb5,10,4,'' -2024-03-26T16:07:10.156785,172.31.48.21,56b1701b36,30,1,'' -2024-03-26T16:07:21.775268,172.31.48.21,06f8f4799b,30,2,'' -2024-03-27T11:37:35.370114,172.31.48.21,7637c6768e,10,1,'pseudo-trigonal symmetry, gamma roughly 60 deg looks very wrong. CN=13 for Zr is also unlikely. Most likely occupantionally disordered' -2024-03-27T11:42:04.475613,172.31.48.21,27e8fe6fe7,60,2,'Looks similar to Laves phases, mostly reasonable interatomic distances + coordination enviroments. Elements are chemically different enough to order' -2024-03-27T11:45:28.699937,172.31.48.21,aba6abc8bf,20,3,'elements are too similar to order, unlikely Re coordination' -2024-03-27T11:47:25.153803,172.31.48.21,aa68bc5ea6,20,4,'Co-coordinations seems unlikely, also fairly large unit cell' -2024-03-27T11:49:03.737105,172.31.48.21,ca0509de66,70,5,'AlB2-type variant which is reasonable, but Ge and Si are likely disordered' -2024-03-27T11:49:20.130023,172.31.48.21,ca0509de66,80,6,'' -2024-03-27T20:23:52.752055,172.31.48.21,e32a217602,20,1,'' -2024-03-27T20:23:58.091685,172.31.48.21,f1114bb798,90,2,'' -2024-03-27T20:25:38.114031,172.31.48.21,e5d42e2749,20,3,'' -2024-03-27T20:25:49.661376,172.31.48.21,d583bca697,20,4,'' -2024-03-27T20:25:56.752197,172.31.48.21,5915704b68,60,5,'' -2024-03-27T20:26:07.494552,172.31.48.21,4d84e5d5b1,80,6,'' -2024-03-27T20:26:16.076629,172.31.48.21,fbca34bf6a,80,7,'' -2024-03-27T20:26:22.654018,172.31.48.21,aa68bc5ea6,10,8,'' -2024-03-27T20:26:31.872105,172.31.48.21,a8e20d3180,20,9,'' -2024-03-27T20:26:32.743277,172.31.48.21,ca39d06493,20,10,'' -2024-03-28T12:32:15.013107,172.31.48.21,5d8f30a894,50,1,'' -2024-03-28T12:33:16.093023,172.31.48.21,5248a8de80,10,1,'a molecular structure like this is extremely unlikely to be stable' -2024-03-28T13:24:00.366851,172.31.48.21,02fb284d16,50,1,'' -2024-03-28T13:24:01.093983,172.31.48.21,5a7f6fa180,50,2,'' -2024-03-28T13:24:13.008022,172.31.48.21,67f06bea1b,50,3,'' -2024-03-28T13:24:34.076199,172.31.48.21,70e240b00d,0,4,'' -2024-03-28T14:00:49.717186,172.31.48.21,4743aff8ac,0,1,'' -2024-03-28T14:01:19.363703,172.31.48.21,e65070289a,0,2,'' diff --git a/src/this_material_does_not_exist/__init__.py b/src/this_material_does_not_exist/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/this_material_does_not_exist/app.py b/src/this_material_does_not_exist/app.py deleted file mode 100644 index ba07fed..0000000 --- a/src/this_material_does_not_exist/app.py +++ /dev/null @@ -1,162 +0,0 @@ -from __future__ import annotations -import datetime -import os -from flask import request -import random -import uuid - -import crystal_toolkit.components as ctc -import dash -import httpx -from crystal_toolkit.settings import SETTINGS -from dash import html -from dash.dependencies import Input, Output, State -from optimade.adapters.structures import Structure as OptimadeStructure - -app = dash.Dash( - assets_folder=str(SETTINGS.ASSETS_PATH), - title="This Material Does Not Exist?", -) - -# Required for gunicorn deployment via app:server -server = app.server - - -structure = None - -structure_component = ctc.StructureMoleculeComponent(structure, id="my_structure") - -layout = html.Div( - [ - html.H2("Does this material exist?"), - structure_component.title_layout(), - html.A(None, id="link"), - structure_component.layout(), - html.Div( - [ - html.H3("What's your likelihood that this material is synthesizable?"), - dash.dcc.Slider( - 0, - 100, - 10, - value=50, - marks={0: "0%", 50: "50%", 100: "100%"}, - id="slider", - ), - html.Label("Why? (Optional):"), - dash.dcc.Textarea( - id="comment-box", - value="", - style={ - "width": "100%", - "height": "50px", - "resize": "vertical", - "padding": "5px", - "font-size": "15px", - "border": "1px solid #ccc", - "border-radius": "5px", - }, - ), - html.Button( - "Submit", - id="submit", - n_clicks=0, - style={ - "margin": "10px", - "padding": "15px 20px", - "font-size": "16px", - "background-color": "#333", - "color": "white", - "border": "none", - "border-radius": "5px", - "cursor": "pointer", - }, - ), - ], - style={ - "width": "350px", - "padding": "20px", - "align": "center", - "text-align": "center", - }, - ), - html.Footer( - [ - html.P( - "Scores will be recorded anonymously and shared publicly if they prove interesting!", - style={"text-align": "center"}, - ), - html.Div( - [ - html.A( - "Powered by OPTIMADE", - href="https://www.optimade.org", - style={"padding": "20px"}, - ), - html.A( - "and Crystal Toolkit", - href="https://docs.crystaltoolkit.org", - style={"padding": "20px"}, - ), - html.A( - "using the GNome dataset", - href="https://github.com/google-deepmind/materials_discovery", - style={"padding": "20px"}, - ), - html.A( - "developed on GitHub", - href="https://github.com/ml-evs/this-material-does-not-exist", - style={"padding": "20px"}, - ), - html.A( - "inspired by", - href="https://thispersondoesnotexist.com/", - style={"padding": "20px"}, - ), - ], - ), - ] - ), - ], - style=dict( - margin="2em auto", display="grid", placeContent="center", placeItems="center" - ), -) - -# tell crystal toolkit about your app and layout -ctc.register_crystal_toolkit(app, layout=layout) - -# random string per user session -session_id = str(uuid.uuid4()) -random.seed(1) -shuffled_entries = random.sample(range(0, 384938), 1000) - - -@app.callback( - Output(structure_component.id(), "data"), - Output("link", "href"), - Output("link", "children"), - Output("comment-box", "value"), - Input("submit", "n_clicks"), - State("slider", "value"), - State("comment-box", "value"), - Input(structure_component.id(), "data"), -) -def get_structure(n_clicks: int, value: str, comment: str, data: dict): - results_fname = os.environ.get("RESULTS_PATH", "results.csv") - timestamp = datetime.datetime.now().isoformat() - if data: - with open(results_fname, "a") as f: - f.write( - f'{timestamp},{request.remote_addr},{data["properties"]["optimade_id"].split()[1]},{value},{n_clicks},{comment!r}\n' - ) - - ind = random.choice(shuffled_entries) - base_url = "https://optimade-gnome.odbx.science/v1/structures" - response = httpx.get(f"{base_url}?page_limit=1&page_offset={ind}").json() - optimade_structure = response["data"][0] - pmg_structure = OptimadeStructure(optimade_structure).as_pymatgen - optimade_id = "GNome " + optimade_structure["id"].split("/")[-1].split(".")[0] - optimade_url = base_url + "/" + optimade_structure["id"] - pmg_structure.properties["optimade_id"] = optimade_id - return pmg_structure, optimade_url, optimade_id, "" diff --git a/swipe/swipe.view.css.ts b/swipe/swipe.view.css.ts new file mode 100644 index 0000000..34280e7 --- /dev/null +++ b/swipe/swipe.view.css.ts @@ -0,0 +1,17 @@ +namespace $.$$ { + + $mol_style_define( $optimade_tmdne_swipe, { + + background: { + color: 'transparent', + }, + + Float: { + userSelect: 'none', + pointerEvents: 'none', + position: 'relative', + }, + + } ) + +} diff --git a/swipe/swipe.view.tree b/swipe/swipe.view.tree new file mode 100644 index 0000000..41222d2 --- /dev/null +++ b/swipe/swipe.view.tree @@ -0,0 +1,29 @@ +$optimade_tmdne_swipe $mol_view + plugins / + <= Touch $mol_touch + allow_draw false + allow_pan <= allowed true + pan? => pan? + speed_threshold 1 + right_threshold <= threshold 60 + left_threshold <= threshold + swipe_distance 300 + transition_smooth \left 0.5s + passed \ + swiped_to? \ + swipe_to_right null + swipe_to_left null + move_to_middle null + x? 0 + sub / + <= Float $mol_view + sub <= content / + style * + left <= left \0px + transition <= transition? \ + + pointer_holding? false + event * + ^ + pointerdown? <=> pointerdown? null + pointerup? <=> pointerup? null diff --git a/swipe/swipe.view.ts b/swipe/swipe.view.ts new file mode 100644 index 0000000..d2d0b49 --- /dev/null +++ b/swipe/swipe.view.ts @@ -0,0 +1,67 @@ +namespace $.$$ { + + export class $optimade_tmdne_swipe extends $.$optimade_tmdne_swipe { + + @ $mol_mem + x( next?: number ): number { + return next ?? ( this.start_x + this.pan().x ) + } + + @ $mol_mem + left(): string { + return this.x() + 'px' + } + + start_x = 0 + start_time?: number + pointerdown( next?: any ) { + this.start_x = parseFloat( $mol_dom_context.getComputedStyle( this.Float().dom_node() ).left ) + this.start_time = (new $mol_time_moment).valueOf() + + this.pan( new $mol_vector_2d( 0, 0 ) ) + this.transition('') + + this.pointer_holding( true ) + } + + pointerup( next?: any ) { + const speed = this.x() / ( (new $mol_time_moment).valueOf() - this.start_time! ) + + if( (this.passed() == 'right') || speed > this.speed_threshold() ) this.swipe_to_right() + else if( (this.passed() == 'left') || speed < ( - this.speed_threshold() ) ) this.swipe_to_left() + else this.move_to_middle() + + this.pointer_holding( false ) + } + + move_to_middle() { + this.transition( this.transition_smooth() ) + this.x( 0 ) + this.swiped_to('') + } + + swipe_to_right() { + this.transition( this.transition_smooth() ) + this.x( this.swipe_distance() ) + this.swiped_to( 'right' ) + } + + swipe_to_left() { + this.transition( this.transition_smooth() ) + this.x( - this.swipe_distance() ) + this.swiped_to( 'left' ) + } + + @ $mol_mem + passed(): string { + const x = this.x() + + if( x < ( - this.left_threshold() ) ) return 'left' + if( x > this.right_threshold() ) return 'right' + + return '' + } + + } + +}