<commit_before>import * as jquery from "jquery";
import {Log} from "../../../../Frame/General/Logging";
import {BaseComponent, FindDOM, Pre, RenderSource, SimpleShouldUpdate, FindDOM_} from "../../../../Frame/UI/ReactGlobals";
import {Vector2i} from "../../../../Frame/General/VectorStructs";
import {Range, DN} from "../../../../Frame/General/Globals";
import Spinner from "../../../../Frame/ReactComponents/Spinner";
import {connect} from "react-redux";
import Select from "../../../../Frame/ReactComponents/Select";
import {ShowMessageBox_Base, ShowMessageBox} from "../../../../Frame/UI/VMessageBox";
import {firebaseConnect} from "react-redux-firebase";
import {GetData} from "../../../../Frame/Database/DatabaseHelpers";
import {Debugger} from "../../../../Frame/General/Globals_Free";
import {RatingType, RatingType_Info} from "../../../../Store/firebase/nodeRatings/@RatingType";
import {Rating} from "../../../../Store/firebase/nodeRatings/@RatingsRoot";
import {MapNode} from "../../../../Store/firebase/nodes/@MapNode";
import {GetUserID} from "../../../../Store/firebase/users";
import {RootState} from "../../../../Store/index";
import {GetRatingUISmoothing, ACTRatingUISmoothnessSet} from "../../../../Store/main/ratingUI";
import {GetNodeChildren, GetParentNode} from "../../../../Store/firebase/nodes";
import {MapNodeType_Info} from "../../../../Store/firebase/nodes/@MapNodeType";
import {Connect} from "../../../../Frame/Database/FirebaseConnect";
import {SignInPanel} from "../../Navbar/UserPanel";
import {AreaChart, Area, XAxis, YAxis, Tooltip, CartesianGrid, Brush, Legend,
	ReferenceArea, ReferenceLine, ReferenceDot, ResponsiveContainer, CartesianAxis} from "recharts";

type RatingsUI_Props = {node: MapNode, path: string, ratingType: RatingType, ratings: Rating[]} & Partial<{nodeChildren: MapNode[]}>;
@Connect((state: RootState, {node, ratingType}: RatingsUI_Props)=> {
	return {
		//myVote: GetData(`nodeRatings/${node._id}/${ratingType}/${GetUserID()}/value`),
		nodeChildren: GetNodeChildren(node),
	};
})
export default class RatingsUI extends BaseComponent<RatingsUI_Props, {size: Vector2i}> {
	render() {
		let {node, path, ratingType, ratings, nodeChildren} = this.props;
		let firebase = store.firebase.helpers;
		let {size} = this.state;

		let parentNode = GetParentNode(path);
		let ratingTypeInfo = RatingType_Info.for[ratingType];
		let options = typeof ratingTypeInfo.options == "function" ? ratingTypeInfo.options(node, parentNode) : ratingTypeInfo.options;
		let userID = GetUserID();
		let myRatingValue = ratings.find(a=>a._key == userID);

		let smoothingOptions = [1, 2, 4, 5, 10, 20, 25, 50, 100].concat(options.Max() == 200 ? [200] : []);
		let minVal = options.Min(), maxVal = options.Max(), range = maxVal - minVal;
		let smoothing = GetRatingUISmoothing();
		smoothing = smoothing.KeepAtMost(options.Max()); // smoothing might have been set higher, from when on another rating-type
		let ticksForChart = options.Select(a=>a.RoundTo(smoothing)).Distinct();
		let dataFinal = ticksForChart.Select(a=>({rating: a, count: 0}));
		for (let entry of ratings) {
			let closestRatingSlot = dataFinal.OrderBy(a=>a.rating.Distance(entry.value)).First();
			closestRatingSlot.count++;
		}

		/*if (ratingType == "strength") {
			let nodeChildren = GetNodeChildren(node);
			let argumentStrength = CalculateArgumentStrength(nodeChildren);
			let closestRatingSlot = dataFinal.OrderBy(a=>a.rating.Distance(argumentStrength)).First();
			closestRatingSlot.count++;
		}*/

		return (
			<div ref="root" style={{position: "relative"/*, minWidth: 496*/}}
					onClick={e=> {
						if (userID == null) {
							return ShowMessageBox({
								title: "Sign in",
								messageUI: ()=> {
									return (
										<div>
											<div>Sign in quickly using...</div>
											<SignInPanel/>
										</div>	
									);
								}
							});
						}

						if (ratingType == "strength") return;
						let target = FindDOM_(e.target);
						//let chart = (target as any).plusParents().filter(".recharts-cartesian-grid");
						let chartHolder = (target as any).plusParents().filter("div.recharts-wrapper");
						if (chartHolder.length == 0) return;

						let chart = chartHolder.find(".recharts-cartesian-grid");
						let posOnChart = new Vector2i(e.pageX - chart.offset().left, e.pageY - chart.offset().top);
						let percentOnChart = posOnChart.x / chart.width();
						let ratingOnChart_exact = minVal + (percentOnChart * range);
						let closestRatingSlot = dataFinal.OrderBy(a=>a.rating.Distance(ratingOnChart_exact)).First();
						let rating = closestRatingSlot.rating;
						
						let finalRating = rating; // range: 0-1
						let boxController = ShowMessageBox({
							title: `Rate ${ratingType} of ${MapNodeType_Info.for[node.type].displayName}`, cancelButton: true,
							messageUI: ()=>(
								<div style={{padding: "10px 0"}}>
									Rating: <Spinner min={options.Min()} max={options.Max()} style={{width: 60}}<commit_msg>* Fixed that clicking on not-chart part of ratings panel would still trigger sign-in panel.<commit_after>import * as jquery from "jquery";
import {Log} from "../../../../Frame/General/Logging";
import {BaseComponent, FindDOM, Pre, RenderSource, SimpleShouldUpdate, FindDOM_} from "../../../../Frame/UI/ReactGlobals";
import {Vector2i} from "../../../../Frame/General/VectorStructs";
import {Range, DN} from "../../../../Frame/General/Globals";
import Spinner from "../../../../Frame/ReactComponents/Spinner";
import {connect} from "react-redux";
import Select from "../../../../Frame/ReactComponents/Select";
import {ShowMessageBox_Base, ShowMessageBox} from "../../../../Frame/UI/VMessageBox";
import {firebaseConnect} from "react-redux-firebase";
import {GetData} from "../../../../Frame/Database/DatabaseHelpers";
import {Debugger} from "../../../../Frame/General/Globals_Free";
import {RatingType, RatingType_Info} from "../../../../Store/firebase/nodeRatings/@RatingType";
import {Rating} from "../../../../Store/firebase/nodeRatings/@RatingsRoot";
import {MapNode} from "../../../../Store/firebase/nodes/@MapNode";
import {GetUserID} from "../../../../Store/firebase/users";
import {RootState} from "../../../../Store/index";
import {GetRatingUISmoothing, ACTRatingUISmoothnessSet} from "../../../../Store/main/ratingUI";
import {GetNodeChildren, GetParentNode} from "../../../../Store/firebase/nodes";
import {MapNodeType_Info} from "../../../../Store/firebase/nodes/@MapNodeType";
import {Connect} from "../../../../Frame/Database/FirebaseConnect";
import {SignInPanel} from "../../Navbar/UserPanel";
import {AreaChart, Area, XAxis, YAxis, Tooltip, CartesianGrid, Brush, Legend,
	ReferenceArea, ReferenceLine, ReferenceDot, ResponsiveContainer, CartesianAxis} from "recharts";

type RatingsUI_Props = {node: MapNode, path: string, ratingType: RatingType, ratings: Rating[]} & Partial<{nodeChildren: MapNode[]}>;
@Connect((state: RootState, {node, ratingType}: RatingsUI_Props)=> {
	return {
		//myVote: GetData(`nodeRatings/${node._id}/${ratingType}/${GetUserID()}/value`),
		nodeChildren: GetNodeChildren(node),
	};
})
export default class RatingsUI extends BaseComponent<RatingsUI_Props, {size: Vector2i}> {
	render() {
		let {node, path, ratingType, ratings, nodeChildren} = this.props;
		let firebase = store.firebase.helpers;
		let {size} = this.state;

		let parentNode = GetParentNode(path);
		let ratingTypeInfo = RatingType_Info.for[ratingType];
		let options = typeof ratingTypeInfo.options == "function" ? ratingTypeInfo.options(node, parentNode) : ratingTypeInfo.options;
		let userID = GetUserID();
		let myRatingValue = ratings.find(a=>a._key == userID);

		let smoothingOptions = [1, 2, 4, 5, 10, 20, 25, 50, 100].concat(options.Max() == 200 ? [200] : []);
		let minVal = options.Min(), maxVal = options.Max(), range = maxVal - minVal;
		let smoothing = GetRatingUISmoothing();
		smoothing = smoothing.KeepAtMost(options.Max()); // smoothing might have been set higher, from when on another rating-type
		let ticksForChart = options.Select(a=>a.RoundTo(smoothing)).Distinct();
		let dataFinal = ticksForChart.Select(a=>({rating: a, count: 0}));
		for (let entry of ratings) {
			let closestRatingSlot = dataFinal.OrderBy(a=>a.rating.Distance(entry.value)).First();
			closestRatingSlot.count++;
		}

		/*if (ratingType == "strength") {
			let nodeChildren = GetNodeChildren(node);
			let argumentStrength = CalculateArgumentStrength(nodeChildren);
			let closestRatingSlot = dataFinal.OrderBy(a=>a.rating.Distance(argumentStrength)).First();
			closestRatingSlot.count++;
		}*/

		return (
			<div ref="root" style={{position: "relative"/*, minWidth: 496*/}}
					onClick={e=> {
						if (ratingType == "strength") return;
						let target = FindDOM_(e.target);
						//let chart = (target as any).plusParents().filter(".recharts-cartesian-grid");
						let chartHolder = (target as any).plusParents().filter("div.recharts-wrapper");
						if (chartHolder.length == 0) return;

						if (userID == null) {
							return ShowMessageBox({
								title: "Sign in",
								messageUI: ()=> {
									return (
										<div>
											<div>Sign in quickly using...</div>
											<SignInPanel/>
										</div>	
									);
								}
							});
						}

						let chart = chartHolder.find(".recharts-cartesian-grid");
						let posOnChart = new Vector2i(e.pageX - chart.offset().left, e.pageY - chart.offset().top);
						let percentOnChart = posOnChart.x / chart.width();
						let ratingOnChart_exact = minVal + (percentOnChart * range);
						let closestRatingSlot = dataFinal.OrderBy(a=>a.rating.Distance(ratingOnChart_exact)).First();
						let rating = closestRatingSlot.rating;
						
						let finalRating = rating; // range: 0-1
						let boxController = ShowMessageBox({
							title: `Rate ${ratingType} of ${MapNodeType_Info.for[node.type].displayName}`, cancelButton: true,
							messageUI: ()=>(
								<div style={{padding: "10px 0"}}>
									Rating: <Spinner min={options.Min()} max={options.Max()} style={{width: 60}}
{'fraction_non_alphanumeric': 0.1819267515923567, 'fraction_numerical': 0.007165605095541401, 'mean_word_length': 3.6011904761904763, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2224945', 'n_tokens_mistral': 3586, 'n_tokens_neox': 3030, 'n_words': 703}