mirror of
https://github.com/soconnor0919/personal-website.git
synced 2025-12-15 16:24:44 -05:00
Citation generator added
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
abstract = {Human-robot interaction (HRI) research plays a pivotal role in shaping how robots communicate and collaborate with humans. However, conducting HRI studies, particularly those employing the Wizard-of-Oz (WoZ) technique, can be challenging. WoZ user studies can have complexities at the technical and methodological levels that may render the results irreproducible. We propose to address these challenges with HRIStudio, a novel web-based platform designed to streamline the design, execution, and analysis of WoZ experiments. HRIStudio offers an intuitive interface for experiment creation, real-time control and monitoring during experimental runs, and comprehensive data logging and playback tools for analysis and reproducibility. By lowering technical barriers, promoting collaboration, and offering methodological guidelines, HRIStudio aims to make human-centered robotics research easier, and at the same time, empower researchers to develop scientifically rigorous user studies.},
|
abstract = {Human-robot interaction (HRI) research plays a pivotal role in shaping how robots communicate and collaborate with humans. However, conducting HRI studies, particularly those employing the Wizard-of-Oz (WoZ) technique, can be challenging. WoZ user studies can have complexities at the technical and methodological levels that may render the results irreproducible. We propose to address these challenges with HRIStudio, a novel web-based platform designed to streamline the design, execution, and analysis of WoZ experiments. HRIStudio offers an intuitive interface for experiment creation, real-time control and monitoring during experimental runs, and comprehensive data logging and playback tools for analysis and reproducibility. By lowering technical barriers, promoting collaboration, and offering methodological guidelines, HRIStudio aims to make human-centered robotics research easier, and at the same time, empower researchers to develop scientifically rigorous user studies.},
|
||||||
author = {O'Connor, Sean and Perrone, L. Felipe},
|
author = {O'Connor, Sean and Perrone, L. Felipe},
|
||||||
title = {HRIStudio: A Framework for Wizard-of-Oz Experiments in Human-Robot Interaction Studies (Late Breaking Report)},
|
title = {HRIStudio: A Framework for Wizard-of-Oz Experiments in Human-Robot Interaction Studies (Late Breaking Report)},
|
||||||
booktitle={33rd IEEE International Conference on Robot and Human Interactive Communication (RO-MAN)},
|
booktitle={33rd IEEE International Conference on Robot and Human Interactive Communication},
|
||||||
year = {2024}
|
year = {2024}
|
||||||
url = {https://soconnor.dev/publications/hristudio-lbr.pdf},
|
url = {https://soconnor.dev/publications/hristudio-lbr.pdf},
|
||||||
paperUrl = {/publications/hristudio-lbr.pdf},
|
paperUrl = {/publications/hristudio-lbr.pdf},
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "~/components/ui/card";
|
import { ArrowUpRight, BookOpenText, FileText, Presentation } from "lucide-react";
|
||||||
import { Badge } from "~/components/ui/badge";
|
|
||||||
import { ArrowUpRight, FileText, Presentation } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { parseBibtex } from "~/lib/bibtex";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import type { Publication } from "~/lib/bibtex";
|
import { Badge } from "~/components/ui/badge";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card";
|
||||||
import { Skeleton } from "~/components/ui/skeleton";
|
import { Skeleton } from "~/components/ui/skeleton";
|
||||||
|
import type { Publication } from "~/lib/bibtex";
|
||||||
|
import { parseBibtex } from "~/lib/bibtex";
|
||||||
|
|
||||||
export default function PublicationsPage() {
|
export default function PublicationsPage() {
|
||||||
const [publications, setPublications] = useState<Publication[]>([]);
|
const [publications, setPublications] = useState<Publication[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
const tagsToStrip = ['paperUrl', 'posterUrl'];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch('/publications.bib')
|
fetch('/publications.bib')
|
||||||
@@ -23,6 +24,38 @@ export default function PublicationsPage() {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const downloadBibtex = (pub: Publication) => {
|
||||||
|
const { title, authors, venue, year, doi, abstract, type, citationType, citationKey } = pub;
|
||||||
|
let bibtexEntry = `@${citationType}{${citationKey},\n`;
|
||||||
|
bibtexEntry += ` title = {${title}},\n`;
|
||||||
|
bibtexEntry += ` author = {${authors.join(' and ')}},\n`;
|
||||||
|
bibtexEntry += ` year = {${year}},\n`;
|
||||||
|
if (type === 'conference' || type === 'workshop') {
|
||||||
|
bibtexEntry += ` organization = {${venue}},\n`;
|
||||||
|
} else if (type === 'journal') {
|
||||||
|
bibtexEntry += ` journal = {${venue}},\n`;
|
||||||
|
} else if (type === 'thesis') {
|
||||||
|
bibtexEntry += ` school = {${venue}},\n`;
|
||||||
|
}
|
||||||
|
if (doi) {
|
||||||
|
bibtexEntry += ` doi = {${doi}},\n`;
|
||||||
|
}
|
||||||
|
if (abstract) {
|
||||||
|
bibtexEntry += ` abstract = {${abstract}},\n`;
|
||||||
|
}
|
||||||
|
bibtexEntry += `}\n`;
|
||||||
|
|
||||||
|
const blob = new Blob([bibtexEntry], { type: 'text/plain' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `refs.bib`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<section className="prose prose-zinc dark:prose-invert max-w-none">
|
<section className="prose prose-zinc dark:prose-invert max-w-none">
|
||||||
@@ -49,9 +82,9 @@ export default function PublicationsPage() {
|
|||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<CardTitle>{pub.title}</CardTitle>
|
<CardTitle>{pub.title}</CardTitle>
|
||||||
{pub.url && (
|
{pub.paperUrl && (
|
||||||
<Link
|
<Link
|
||||||
href={pub.url}
|
href={pub.paperUrl}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-muted-foreground hover:text-primary"
|
className="text-muted-foreground hover:text-primary"
|
||||||
@@ -113,6 +146,14 @@ export default function PublicationsPage() {
|
|||||||
</Badge>
|
</Badge>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
<Badge
|
||||||
|
onClick={() => downloadBibtex(pub)}
|
||||||
|
className="cursor-pointer capitalize"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
<BookOpenText className="h-4 w-4" />
|
||||||
|
BibTeX
|
||||||
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ export type Publication = {
|
|||||||
paperUrl?: string;
|
paperUrl?: string;
|
||||||
posterUrl?: string;
|
posterUrl?: string;
|
||||||
abstract?: string;
|
abstract?: string;
|
||||||
|
citationType?: string;
|
||||||
|
citationKey?: string;
|
||||||
type: 'conference' | 'journal' | 'workshop' | 'thesis';
|
type: 'conference' | 'journal' | 'workshop' | 'thesis';
|
||||||
};
|
};
|
||||||
|
|
||||||
type BibTeXEntry = {
|
type BibTeXEntry = {
|
||||||
type: string;
|
type: string;
|
||||||
fields: Record<string, string>;
|
fields: Record<string, string>;
|
||||||
|
citationKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseAuthors(authorString: string): string[] {
|
function parseAuthors(authorString: string): string[] {
|
||||||
@@ -31,10 +34,11 @@ function parseAuthors(authorString: string): string[] {
|
|||||||
|
|
||||||
function parseBibTeXEntry(entry: string): BibTeXEntry | null {
|
function parseBibTeXEntry(entry: string): BibTeXEntry | null {
|
||||||
// Match the entry type and content
|
// Match the entry type and content
|
||||||
const typeMatch = entry.match(/^(\w+)\s*{\s*[\w\d-_]+\s*,/);
|
const typeMatch = entry.match(/^(\w+)\s*{\s*([\w\d-_]+)\s*,/);
|
||||||
if (!typeMatch) return null;
|
if (!typeMatch) return null;
|
||||||
|
|
||||||
const type = typeMatch[1]!.toLowerCase();
|
const type = typeMatch[1]!.toLowerCase();
|
||||||
|
const citationKey = typeMatch[2];
|
||||||
const content = entry.slice(typeMatch[0].length);
|
const content = entry.slice(typeMatch[0].length);
|
||||||
|
|
||||||
const fields: Record<string, string> = {};
|
const fields: Record<string, string> = {};
|
||||||
@@ -68,7 +72,7 @@ function parseBibTeXEntry(entry: string): BibTeXEntry | null {
|
|||||||
fields[currentField] = buffer.trim();
|
fields[currentField] = buffer.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
return { type, fields };
|
return { type, fields, citationKey: citationKey! };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseBibtex(bibtex: string): Publication[] {
|
export function parseBibtex(bibtex: string): Publication[] {
|
||||||
@@ -79,10 +83,21 @@ export function parseBibtex(bibtex: string): Publication[] {
|
|||||||
.filter((entry): entry is BibTeXEntry => entry !== null);
|
.filter((entry): entry is BibTeXEntry => entry !== null);
|
||||||
|
|
||||||
return entries.map(entry => {
|
return entries.map(entry => {
|
||||||
const publicationType =
|
const publicationType = (() => {
|
||||||
entry.type === 'inproceedings' ? 'conference' :
|
switch (entry.type) {
|
||||||
entry.type === 'article' ? 'journal' :
|
case 'inproceedings':
|
||||||
entry.type === 'mastersthesis' ? 'thesis' : 'workshop';
|
case 'conference':
|
||||||
|
return 'conference';
|
||||||
|
case 'article':
|
||||||
|
return 'journal';
|
||||||
|
case 'mastersthesis':
|
||||||
|
return 'thesis';
|
||||||
|
case 'workshop':
|
||||||
|
return 'workshop';
|
||||||
|
default:
|
||||||
|
return 'journal';
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: entry.fields.title?.replace(/[{}]/g, '') || '',
|
title: entry.fields.title?.replace(/[{}]/g, '') || '',
|
||||||
@@ -94,6 +109,8 @@ export function parseBibtex(bibtex: string): Publication[] {
|
|||||||
paperUrl: entry.fields.paperurl,
|
paperUrl: entry.fields.paperurl,
|
||||||
posterUrl: entry.fields.posterurl,
|
posterUrl: entry.fields.posterurl,
|
||||||
abstract: entry.fields.abstract,
|
abstract: entry.fields.abstract,
|
||||||
|
citationType: entry.type,
|
||||||
|
citationKey: entry.citationKey,
|
||||||
type: publicationType
|
type: publicationType
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user