shape onModel improvements; vline fixes; time entry; couple bugs remain with dca dragging

This commit is contained in:
Tim
2024-04-19 19:51:06 -04:00
parent 1579060024
commit 59342e2e26
9 changed files with 457 additions and 144 deletions

View File

@@ -3,8 +3,8 @@
</template>
<script setup>
import "/public/charting_library/charting_library.js"
// import "/public/datafeeds/udf/dist/bundle.js"
import "/charting_library/charting_library.js?url"
// import "/datafeeds/udf/dist/bundle.js?url"
import {onMounted, ref} from "vue";
import {initWidget} from "@/charts/chart.js";

View File

@@ -1,19 +1,53 @@
<template>
<rung-builder name='DCA' :order="order" :builder="builder"
v-model:value-a="absTimeA" v-model:value-b="absTimeB" :mode="1" :flip="flipped"
v-model:value-a="absTimeA" v-model:value-b="absTimeB"
:shape="VLine"
:mode="1" :flip="flipped" :orientation="0"
:get-model-value="getModelValue" :set-model-value="setModelValue"
:get-points-value="getPointsValue"
:set-values="setValues" :set-weights="setWeights"
:std-width="stdWidth" :build-tranches="buildTranches">
<!--
<v-list style="background-color: inherit">
<v-list-item v-for="t in absoluteTimes">{{t}}</v-list-item>
</v-list>
-->
<table>
<tbody>
<tr>
<td>
<absolute-time-entry v-model="absTimeA"/>
</td>
<td class="weight">{{ weights.length ? allocationText(weights[0]) : '' }}</td>
</tr>
<tr v-if="weights.length>2" v-for="i in weights.length-2" class="ml-5">
<td class="pl-5">{{ times[1+i] }}</td>
<td class="weight">{{ allocationText(weights[1+i]) }}</td>
</tr>
<tr v-if="weights.length>1">
<td>
<!--
<v-text-field type="number" v-model="lowerPrice" min="0"
density="compact" hide-details class="mx-1 my-2" variant="outlined"
label="Price"
:color="color" :base-color="color"
style="flex: 6em"
/>
-->
</td>
<td class="weight">{{ allocationText(weights[weights.length-1]) }}</td>
</tr>
</tbody>
</table>
</rung-builder>
</template>
<script setup>
import {builderDefaults, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
import {allocationText, builderDefaults, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
import {VLine} from "@/charts/shape.js";
import {sideColor} from "@/misc.js";
import {useTheme} from "vuetify";
@@ -22,6 +56,8 @@ import {DISTANT_FUTURE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js
import RungBuilder from "@/components/chart/RungBuilder.vue";
import {computed, ref, watchEffect} from "vue";
import {chart, dragging} from "@/charts/chart.js";
import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue";
import TimeEntry from "@/components/TimeEntry.vue";
const s = useStore()
const os = useOrderStore()
@@ -50,10 +86,9 @@ builderDefaults(props.builder, {
color: defaultColor,
})
const rawTimes = ref([])
const times = ref([])
const weights = ref([])
const times = computed(()=>rawTimes.value.map((t)=>Math.round(t)))
const endTimes = computed(()=>{
if (props.builder.rungs === 1)
return DISTANT_FUTURE
@@ -63,10 +98,10 @@ const endTimes = computed(()=>{
})
const absoluteTimes = computed(()=>{
// console.log('absoluteTimes', props.builder.relative, times.value)
if (!props.builder.relative)
// if (!props.builder.relative)
return times.value
const now = s.clock
return times.value.map((t)=>now+t)
// const now = s.clock
// return times.value.map((t)=>now+t)
})
@@ -77,7 +112,7 @@ watchEffect(()=>{
const range = chart.getVisibleRange()
const width = range.to - range.from
const now = s.clock
const extra = (Math.max(0,endTime - now) + minWidth.value) / width
const extra = (Math.max(0,endTime - now) + stdWidth.value/2) / width
// console.log('visrange', range, width, absV)
if (range.to < endTime) {
// console.log('scrolling')
@@ -93,39 +128,38 @@ watchEffect(()=>{
const absTimeA = computed({
get() {
let result = props.builder.timeA
if (props.builder.relative)
result += s.clock
// console.log('absTimeA', result)
// if (props.builder.relative)
// result += s.clock
console.log('get absTimeA', result)
return result
},
set(v) {
// console.log('set absTimeA', props.builder.timeA, v)
if (props.builder.relative)
v -= s.clock
console.error('set absTimeA', props.builder.timeA, v)
// if (props.builder.relative)
// v -= s.clock
props.builder.timeA = v
// console.log('absTimeA=',props.builder.timeA)
scroll()
console.log('absTimeA=',props.builder.timeA)
}
})
const absTimeB = computed({
get() {
let result = props.builder.timeB
if (props.builder.relative)
result += s.clock
// if (props.builder.relative)
// result += s.clock
// console.log('absTimeB', result)
return result
},
set(v) {
// console.log('set absTimeB', props.builder.timeB, v)
const absV = v
if ( v !== null && props.builder.relative )
v -= s.clock
console.error('set absTimeB', props.builder.timeB, v)
// if ( v !== null && props.builder.relative )
// v -= s.clock
props.builder.timeB = v
const maxA = v - minWidth.value;
if (props.builder.timeA > maxA)
if (props.builder.timeA > maxA) {
console.log('scootching A to', maxA)
props.builder.timeA = maxA
// console.log('absTimeB=',props.builder.timeB)
scroll()
}
console.log('absTimeB=',props.builder.timeB)
}
})
@@ -135,37 +169,6 @@ const flipped = computed(()=>{
return a !== null && b !== null && a > b
})
const higherIndex = computed(()=>flipped.value ? 0 : weights.value.length-1)
const lowerIndex = computed(()=>!flipped.value ? 0 : weights.value.length-1)
const innerIndexes = computed(()=>{
const n = times.value.length
const f = flipped.value
const result = []
for (let i=1; i<n-1; i++)
result.push(f?i:n-1-i)
return result
})
const earlierTime = computed({
get() { return !flipped.value ? props.builder.timeA : props.builder.timeB },
set(v) {
if (!flipped.value)
props.builder.timeA = v
else
props.builder.timeB = v
}
})
const laterTime = computed({
get() { return !flipped.value ? props.builder.timeA : props.builder.timeB },
set(v) {
if (!flipped.value)
props.builder.timeA = v
else
props.builder.timeB = v
}
})
function buildTranches() {
const order = props.order
const builder = props.builder
@@ -201,7 +204,8 @@ function getPointsValue(points) {
function setModelValue(model, value) {
// console.log('DCA set model value', model, value)
const v = value === null ? null : props.builder.relative ? s.clock + Math.round(value) : Math.round(value)
// const v = value === null ? null : props.builder.relative ? s.clock + Math.round(value) : Math.round(value)
const v = value === null ? null : Math.round(value)
if (model.time !== v) {
// console.log('DCA do set time', v)
model.time = v
@@ -209,12 +213,15 @@ function setModelValue(model, value) {
}
function setValues(values) {
times.value = values.map((t)=>Math.round(t))
/*
if (!props.builder.relative)
rawTimes.value = values
else {
const now = s.clock
rawTimes.value = values.map((v)=>v-now)
}
*/
}
function setWeights(ws) { weights.value = ws }

View File

@@ -20,7 +20,7 @@
Click the chart!
</div>
<div v-if="rungs>1" class="mx-2 d-flex align-center">
<v-slider v-if="rungs>1" direction="vertical" min="-100" max="100" v-model="skew100"
<v-slider v-if="rungs>1" :direction="orientation?'vertical':'horizontal'" min="-100" max="100" v-model="skew100"
class="no-slider-bg ml-2 mr-4" hide-details/>
<v-text-field type="number" v-model="skew100" min="-100" max="100"
density="compact" hide-details variant="outlined" label="Skew" step="5"
@@ -41,7 +41,7 @@ import {useTheme} from "vuetify";
import {linspace, sideColor} from "@/misc.js";
import {computed, onUnmounted, watchEffect} from "vue";
import Color from "color";
import {cancelDrawing, chart} from "@/charts/chart.js";
import {cancelDrawing} from "@/charts/chart.js";
const os = useOrderStore()
const co = useChartOrderStore()
@@ -57,6 +57,7 @@ const props = defineProps({
shape: Function, // shape() -> Shape
mode: { type: Number, default: 0 }, // rung addition mode: 0 = split, 1 = extend
flip: { type: Boolean, default: false }, // if true, the skew slider is flipped upside-down
orientation: { type: Number, default: 1 }, // 0 = horizontal slider, 1 = vertical
getModelValue: Function, // getModelValue(model) -> value
setModelValue: Function, // setModelValue(model,value) -> void
getPointsValue: Function, // getValueFromPoints(points) -> value
@@ -89,6 +90,7 @@ const rungs = computed({
props.builder.rungs = 1
return
}
const prevR = props.builder.rungs
r = Number(r)
props.builder.rungs = r
const b = valueB.value
@@ -115,8 +117,10 @@ const rungs = computed({
}
else {
// from multi to multi
if (props.mode===1)
valueB.value = valueA.value + props.stdWidth * (r-1)
if (props.mode===1) {
const width = (valueB.value - valueA.value) / (prevR-1)
valueB.value = valueA.value + width * (r-1)
}
}
}
})
@@ -182,82 +186,62 @@ function createShape(value, model, onModel, onDelete) {
}
function translateOnDrag(shape) {
const oldOnPoints = shape.onPoints
shape.onPoints = function (points) {
function translateOnModel(shape) {
const oldOnModel = shape.onModel
shape.onModel = function (model, oldModel) {
oldOnModel.call(this, ...arguments)
// console.log('translateOnDrag', this.beingDragged(), shape.ourPoints)
if (!this.beingDragged()) {
oldOnPoints.call(this, points)
oldOnModel.call(this, ...arguments)
return
}
const prev = props.getModelValue(this.model)
oldOnPoints.call(this, points)
const prev = props.getModelValue(oldModel)
const cur = props.getModelValue(this.model)
const delta = cur - prev
// console.log('delta', points, shape.ourPoints, prev, cur, delta)
// console.log('delta', shape.id, prev, cur, delta)
if (delta !== 0) {
valueA.value += delta
valueB.value += delta
if (rungs.value > 1)
valueB.value += delta
}
}
}
// function translateOnDrag(shape) {
// const oldOnPoints = shape.onPoints
// shape.onPoints = function (points) {
// console.log('translateOnDrag', this.beingDragged(), shape.ourPoints)
// if (!this.beingDragged()) {
// oldOnPoints.call(this, points)
// return
// }
//
// // todo vectorize
// const prev = props.getPointsValue(shape.ourPoints)
// const cur = props.getPointsValue(points)
// const delta = cur - prev
// console.log('delta', points, shape.ourPoints, prev, cur, delta)
// if (delta !== 0) {
// valueA.value += delta
// valueB.value += delta
// }
// oldOnPoints.call(this, points)
// }
// }
function setModelColor(model) {
if (model.color && model.color !== color.value)
color.value = model.color
}
const shapeA = createShape(valueA.value, {color: defaultColor},
function (model) {
const value = props.getModelValue(model);
if (value!==null && value!==undefined)
if (value !== valueA.value)
valueA.value = value;
if (model.color)
color.value = model.color
setModelColor(model)
},
deleteSelf)
if (props.mode===1)
translateOnDrag(shapeA)
translateOnModel(shapeA)
const shapeB = createShape(valueB.value, {color:defaultColor},
function (model) {
const value = props.getModelValue(model);
if (value!==null && value!==undefined)
if (value !== valueB.value)
valueB.value = value;
if (model.color)
color.value = model.color
setModelColor(model)
},
deleteSelf)
function interiorOnModel(model) {
if (model.color)
color.value = model.color
setModelColor(model)
}
let interiorShapes = []
function createInteriorShape(index) {
const shape = new props.shape(makeModel(index), interiorOnModel, deleteSelf)
translateOnDrag(shape)
translateOnModel(shape)
interiorShapes.push(shape)
}
@@ -388,6 +372,9 @@ if (!valueA.value)
:deep(.v-slider.v-input--vertical > .v-input__control) {
min-height: 5em !important;
}
:deep(.v-slider.v-input--horizontal > .v-input__control) {
min-width: 5em !important;
}
:deep(.v-slider.no-slider-bg .v-slider-track__fill) {
background-color: inherit !important;
}